diff --git a/app/_data/docs_nav_gateway_2.6.x.yml b/app/_data/docs_nav_gateway_2.6.x.yml new file mode 100644 index 000000000000..7de8ab94ecc4 --- /dev/null +++ b/app/_data/docs_nav_gateway_2.6.x.yml @@ -0,0 +1,461 @@ +- title: Introduction + icon: /assets/images/icons/documentation/icn-flag.svg + url: /gateway/2.6.x/ + absolute_url: true + items: + - text: Version Support Policy + url: /gateway/latest/support-policy + absolute_url: true + - text: Compatibility + url: /compatibility/ + - text: Changelog + url: /gateway/changelog + absolute_url: true + +- title: Install and Run + icon: /assets/images/icons/documentation/icn-deployment-color.svg + url: /install-and-run/ + items: + - text: Kubernetes + url: /install-and-run/kubernetes + - text: Helm + url: /install-and-run/helm + - text: OpenShift with Helm + url: /install-and-run/openshift + - text: Docker + url: /install-and-run/docker + - text: Amazon Linux + url: /install-and-run/amazon-linux + - text: CentOS + url: /install-and-run/centos + - text: Debian + url: /install-and-run/debian + - text: RHEL + url: /install-and-run/rhel + - text: Ubuntu + url: /install-and-run/ubuntu + - text: Migrating from OSS to EE + url: /install-and-run/migrate-ce-to-ke + - text: Upgrade Kong Gateway + url: /install-and-run/upgrade-enterprise + - text: Upgrade Kong Gateway OSS + url: /install-and-run/upgrade-oss + +- title: Get Started + icon: /assets/images/icons/documentation/icn-quickstart-color.svg + items: + - text: Quickstart Guide + url: /get-started/quickstart + items: + - text: Configuring a Service + url: /get-started/quickstart/configuring-a-service + - text: Configuring a gRPC Service + url: /get-started/quickstart/configuring-a-grpc-service + - text: Enabling Plugins + url: /get-started/quickstart/enabling-plugins + - text: Adding Consumers + url: /get-started/quickstart/adding-consumers + - text: Comprehensive Guide + url: /get-started/comprehensive + items: + - text: Prepare to Administer + url: /get-started/comprehensive/prepare + - text: Expose your Services + url: /get-started/comprehensive/expose-services + - text: Protect your Services + url: /get-started/comprehensive/protect-services + - text: Improve Performance + url: /get-started/comprehensive/improve-performance + - text: Secure Services + url: /get-started/comprehensive/secure-services + - text: Set Up Intelligent Load Balancing + url: /get-started/comprehensive/load-balancing + - text: Manage Administrative Teams + url: /get-started/comprehensive/manage-teams + - text: Publish, Locate, and Consume Services + url: /get-started/comprehensive/dev-portal + +- title: Plan and Deploy + icon: /assets/images/icons/documentation/icn-deployment-color.svg + items: + - text: Running Kong as a Non-Root User + url: /plan-and-deploy/kong-user + - text: Resource Sizing Guidelines + url: /plan-and-deploy/sizing-guidelines + - text: Hybrid Mode + url: /plan-and-deploy/hybrid-mode + items: + - text: Deploy Kong Gateway in Hybrid Mode + url: /plan-and-deploy/hybrid-mode/hybrid-mode-setup + - text: Kubernetes Deployment Options + url: /plan-and-deploy/kubernetes-deployment-options + - text: Control Kong Gateway through systemd + url: /plan-and-deploy/systemd + - text: Performance Testing Framework + url: /plan-and-deploy/performance-testing-framework + - text: DNS Considerations + url: /plan-and-deploy/dns-considerations + - text: Default Ports + url: /plan-and-deploy/default-ports + - text: Licenses + url: /plan-and-deploy/licenses + items: + - text: Access Your License + url: /plan-and-deploy/licenses/access-license + - text: Deploy Your License + url: /plan-and-deploy/licenses/deploy-license + - text: Monitor License Usage + url: /plan-and-deploy/licenses/report + - text: Security + items: + - text: Start Kong Gateway Securely + url: /plan-and-deploy/security/start-kong-securely + - text: Keyring and Data Encryption + url: /plan-and-deploy/security/db-encryption + - text: Kong Security Update Process + url: /plan-and-deploy/security/kong-security-update-process + +- title: Configure + icon: /assets/images/icons/konnect/konnect-settings.svg + items: + - text: Authentication and Authorization + items: + - text: Authentication Reference + url: /configure/auth + - text: OpenID Connect Plugin + url: /configure/auth/oidc-use-case + items: + - text: OpenID Connect with Curity + url: /configure/auth/oidc-curity + - text: OpenID Connect with Azure AD + url: /configure/auth/oidc-azuread + - text: OpenID Connect with Google + url: /configure/auth/oidc-google + - text: OpenID Connect with Okta + url: /configure/auth/oidc-okta + - text: OpenID Connect with Auth0 + url: /configure/auth/oidc-auth0 + - text: OpenID Connect with Cognito + url: /configure/auth/oidc-cognito + - text: OIDC Authenticated Group Mapping + url: /configure/auth/oidc-mapping + - text: OpenID Connect Plugin Reference + url: /hub/kong-inc/openid-connect + absolute_url: true + - text: Allowing Multiple Authentication Methods + url: /configure/auth/allowing-multiple-authentication-methods + - text: Auth for Kong Manager + url: /configure/auth/kong-manager + items: + - text: Create a Super Admin + url: /configure/auth/kong-manager/super-admin + - text: Configure Networking + url: /configure/auth/kong-manager/networking + - text: Configure Kong Manager to Send Email + url: /configure/auth/kong-manager/email + - text: Reset Passwords and RBAC Tokens + url: /configure/auth/kong-manager/reset-password/ + - text: Configure Workspaces + url: /configure/auth/kong-manager/workspaces + - text: Basic Auth + url: /configure/auth/kong-manager/basic + - text: LDAP + url: /configure/auth/kong-manager/ldap + - text: OIDC + url: /configure/auth/kong-manager/oidc + - text: Sessions + url: /configure/auth/kong-manager/sessions + + - text: Role-based Access Control (RBAC) + url: /configure/auth/rbac + items: + - text: Add a Role + url: /configure/auth/rbac/add-role + - text: Add a User + url: /configure/auth/rbac/add-user + - text: Add an Admin + url: /configure/auth/rbac/add-admin + - text: Mapping LDAP Service Directory Groups to Kong Roles + url: /configure/auth/service-directory-mapping + - text: Kong Dev Portal + url: /developer-portal/ + items: + - text: Enable the Dev Portal + url: /developer-portal/enable-dev-portal + - text: Structure and File Types + url: /developer-portal/structure-and-file-types + - text: Using the Portal Files API + url: /developer-portal/files-api + - text: Working with Templates + url: /developer-portal/working-with-templates + - text: Using the Editor + url: /developer-portal/using-the-editor + # commented out for now, as this redirects to an old doc version + # - text: Networking + # url: /developer-portal/networking + - text: Configuration + items: + - text: Authentication + items: + - text: Basic Auth + url: /developer-portal/configuration/authentication/basic-auth + - text: Key Auth + url: /developer-portal/configuration/authentication/key-auth + - text: OIDC + url: /developer-portal/configuration/authentication/oidc + - text: Sessions + url: /developer-portal/configuration/authentication/sessions + - text: Adding Custom Registration Fields + url: /developer-portal/configuration/authentication/adding-registration-fields + - text: SMTP + url: /developer-portal/configuration/smtp + - text: Workspaces + url: /developer-portal/configuration/workspaces + - text: Administration + items: + - text: Manage Developers + url: /developer-portal/administration/managing-developers + - text: Developer Roles and Content Permissions + url: /developer-portal/administration/developer-permissions + - text: Application Registration + items: + - text: Authorization Provider Strategy + url: /developer-portal/administration/application-registration/auth-provider-strategy + - text: Enable Application Registration + url: /developer-portal/administration/application-registration/enable-application-registration + - text: Enable Key Authentication for Application Registration + url: /developer-portal/administration/application-registration/enable-key-auth-plugin + - text: External OAuth2 Support + url: /developer-portal/administration/application-registration/3rd-party-oauth + - text: Set up Okta and Kong for external OAuth + url: /developer-portal/administration/application-registration/okta-config + - text: Set Up Azure AD and Kong for External Authentication + url: /developer-portal/administration/application-registration/azure-oidc-config + - text: Manage Applications + url: /developer-portal/administration/application-registration/managing-applications + - text: Customization + items: + - text: Easy Theme Editing + url: /developer-portal/theme-customization/easy-theme-editing + - text: Markdown Rendering Module + url: /developer-portal/theme-customization/markdown-extended + - text: Customizing Portal Emails + url: /developer-portal/theme-customization/emails + - text: Adding and Using JavaScript Assets + url: /developer-portal/theme-customization/adding-javascript-assets + - text: Single Page App in Dev Portal + url: /developer-portal/theme-customization/single-page-app + - text: Helpers CLI + url: /developer-portal/helpers/cli + + - text: Configure gRPC Plugins + url: /configure/grpc + - text: GraphQL Quickstart + url: /configure/graphql-quickstart + - text: Logging Reference + url: /configure/logging + - text: Network and Firewall + url: /configure/network + +- title: Monitor + icon: /assets/images/icons/documentation/icn-vitals.svg + items: + - text: Kong Vitals + url: /vitals + items: + - text: Metrics + url: /vitals/vitals-metrics + - text: Reports + url: /vitals/vitals-reports + - text: Vitals with InfluxDB + url: /vitals/vitals-influx-strategy + - text: Vitals with Prometheus + url: /vitals/vitals-prometheus-strategy + - text: Prometheus plugin + url: /hub/kong-inc/prometheus + absolute_url: true + - text: Zipkin plugin + url: /hub/kong-inc/zipkin + absolute_url: true + +# - title: Develop +# icon: /assets/images/icons/documentation/icn-dev-portal-color.svg +# items: + +- title: Reference + icon: /assets/images/icons/documentation/icn-references-color.svg + items: + - text: Admin API + url: /admin-api + items: + - text: DB-less Mode + url: /admin-api/#db-less-mode + - text: Declarative Configuration + url: /admin-api/#declarative-configuration + - text: Supported Content Types + url: /admin-api/#supported-content-types + - text: Information Routes + url: /admin-api/#information-routes + - text: Health Routes + url: /admin-api/#health-routes + - text: Tags + url: /admin-api/#tags + - text: Service Object + url: /admin-api/#service-object + - text: Route Object + url: /admin-api/#route-object + - text: Consumer Object + url: /admin-api/#consumer-object + - text: Plugin Object + url: /admin-api/#plugin-object + - text: Certificate Object + url: /admin-api/#certificate-object + - text: CA Certificate Object + url: /admin-api/#ca-certificate-object + - text: SNI Object + url: /admin-api/#sni-object + - text: Upstream Object + url: /admin-api/#upstream-object + - text: Target Object + url: /admin-api/#target-object + - text: Licenses + url: /admin-api/licenses/reference + items: + - text: Licenses Reference + url: /admin-api/licenses/reference + - text: Licenses Examples + url: /admin-api/licenses/examples + - text: Workspaces + url: /admin-api/workspaces/reference + items: + - text: Workspaces Reference + url: /admin-api/workspaces/reference + - text: Workspace Examples + url: /admin-api/workspaces/examples + - text: RBAC + url: /admin-api/rbac/reference + items: + - text: RBAC Reference + url: /admin-api/rbac/reference + - text: RBAC Examples + url: /admin-api/rbac/examples + - text: Admins + url: /admin-api/admins/reference + items: + - text: API Reference + url: /admin-api/admins/reference + - text: Examples + url: /admin-api/admins/examples + - text: Event Hooks + url: /admin-api/event-hooks/reference + items: + - text: Event Hooks Reference + url: /admin-api/event-hooks/reference + - text: Examples + url: /admin-api/event-hooks/examples + - text: Audit Logging + url: /admin-api/audit-log + - text: Keyring and Data Encryption + url: /admin-api/db-encryption + - text: Securing the Admin API + url: /admin-api/secure-admin-api + - text: DB-less and Declarative Configuration + url: /reference/db-less-and-declarative-config + - text: Configuration Reference + url: /reference/configuration + - text: CLI Reference + url: /reference/cli + - text: Load Balancing Reference + url: /reference/loadbalancing + - text: Proxy Reference + url: /reference/proxy + - text: Rate Limiting Library + url: /reference/rate-limiting + - text: Health Checks and Circuit Breakers Reference + url: /reference/health-checks-circuit-breakers + - text: Clustering Reference + url: /reference/clustering + + - text: Plugin Development Kit + url: /pdk + items: + - text: kong.client + url: /pdk/kong.client + + - text: kong.client.tls + url: /pdk/kong.client.tls + + - text: kong.cluster + url: /pdk/kong.cluster + + - text: kong.ctx + url: /pdk/kong.ctx + + - text: kong.ip + url: /pdk/kong.ip + + - text: kong.log + url: /pdk/kong.log + + - text: kong.nginx + url: /pdk/kong.nginx + + - text: kong.node + url: /pdk/kong.node + + - text: kong.request + url: /pdk/kong.request + + - text: kong.response + url: /pdk/kong.response + + - text: kong.router + url: /pdk/kong.router + + - text: kong.service + url: /pdk/kong.service + + - text: kong.service.request + url: /pdk/kong.service.request + + - text: kong.service.response + url: /pdk/kong.service.response + + - text: kong.table + url: /pdk/kong.table + + - text: Plugin Development Guide + url: /plugin-development + items: + - text: Introduction + url: /plugin-development + + - text: File structure + url: /plugin-development/file-structure + + - text: Implementing custom logic + url: /plugin-development/custom-logic + + - text: Plugin configuration + url: /plugin-development/plugin-configuration + + - text: Accessing the datastore + url: /plugin-development/access-the-datastore + + - text: Storing custom entities + url: /plugin-development/custom-entities + + - text: Caching custom entities + url: /plugin-development/entities-cache + + - text: Extending the Admin API + url: /plugin-development/admin-api + + - text: Writing tests + url: /plugin-development/tests + + - text: (un)Installing your plugin + url: /plugin-development/distribution + + - text: Plugins in Other Languages + url: /reference/external-plugins diff --git a/app/_data/docs_nav_gateway_2.7.x.yml b/app/_data/docs_nav_gateway_2.7.x.yml new file mode 100644 index 000000000000..d6711c355a9f --- /dev/null +++ b/app/_data/docs_nav_gateway_2.7.x.yml @@ -0,0 +1,473 @@ +- title: Introduction + icon: /assets/images/icons/documentation/icn-flag.svg + url: /gateway/2.7.x/ + absolute_url: true + items: + - text: Version Support Policy + url: /gateway/latest/support-policy + absolute_url: true + - text: Compatibility + url: /compatibility/ + - text: Changelog + url: /gateway/changelog + absolute_url: true + +- title: Install and Run + icon: /assets/images/icons/documentation/icn-deployment-color.svg + url: /install-and-run/ + items: + - text: Kubernetes + url: /install-and-run/kubernetes + - text: Helm + url: /install-and-run/helm + - text: OpenShift with Helm + url: /install-and-run/openshift + - text: Docker + url: /install-and-run/docker + - text: Amazon Linux + url: /install-and-run/amazon-linux + - text: CentOS + url: /install-and-run/centos + - text: Debian + url: /install-and-run/debian + - text: RHEL + url: /install-and-run/rhel + - text: Ubuntu + url: /install-and-run/ubuntu + - text: Migrating from OSS to EE + url: /install-and-run/migrate-ce-to-ke + - text: Upgrade Kong Gateway + url: /install-and-run/upgrade-enterprise + - text: Upgrade Kong Gateway OSS + url: /install-and-run/upgrade-oss + +- title: Get Started + icon: /assets/images/icons/documentation/icn-quickstart-color.svg + items: + - text: Quickstart Guide + url: /get-started/quickstart + items: + - text: Configuring a Service + url: /get-started/quickstart/configuring-a-service + - text: Configuring a gRPC Service + url: /get-started/quickstart/configuring-a-grpc-service + - text: Enabling Plugins + url: /get-started/quickstart/enabling-plugins + - text: Adding Consumers + url: /get-started/quickstart/adding-consumers + - text: Comprehensive Guide + url: /get-started/comprehensive + items: + - text: Prepare to Administer + url: /get-started/comprehensive/prepare + - text: Expose your Services + url: /get-started/comprehensive/expose-services + - text: Protect your Services + url: /get-started/comprehensive/protect-services + - text: Improve Performance + url: /get-started/comprehensive/improve-performance + - text: Secure Services + url: /get-started/comprehensive/secure-services + - text: Set Up Intelligent Load Balancing + url: /get-started/comprehensive/load-balancing + - text: Manage Administrative Teams + url: /get-started/comprehensive/manage-teams + - text: Publish, Locate, and Consume Services + url: /get-started/comprehensive/dev-portal + +- title: Plan and Deploy + icon: /assets/images/icons/documentation/icn-deployment-color.svg + items: + - text: Running Kong as a Non-Root User + url: /plan-and-deploy/kong-user + - text: Resource Sizing Guidelines + url: /plan-and-deploy/sizing-guidelines + - text: Hybrid Mode + url: /plan-and-deploy/hybrid-mode + items: + - text: Deploy Kong Gateway in Hybrid Mode + url: /plan-and-deploy/hybrid-mode/hybrid-mode-setup + - text: Kubernetes Deployment Options + url: /plan-and-deploy/kubernetes-deployment-options + - text: Control Kong Gateway through systemd + url: /plan-and-deploy/systemd + - text: Performance Testing Framework + url: /plan-and-deploy/performance-testing-framework + - text: DNS Considerations + url: /plan-and-deploy/dns-considerations + - text: Default Ports + url: /plan-and-deploy/default-ports + - text: Licenses + url: /plan-and-deploy/licenses + items: + - text: Access Your License + url: /plan-and-deploy/licenses/access-license + - text: Deploy Your License + url: /plan-and-deploy/licenses/deploy-license + - text: Monitor License Usage + url: /plan-and-deploy/licenses/report + - text: Security + items: + - text: Start Kong Gateway Securely + url: /plan-and-deploy/security/start-kong-securely + - text: Keyring and Data Encryption + url: /plan-and-deploy/security/db-encryption + - text: Kong Security Update Process + url: /plan-and-deploy/security/kong-security-update-process + +- title: Configure + icon: /assets/images/icons/konnect/konnect-settings.svg + items: + - text: Authentication and Authorization + items: + - text: Authentication Reference + url: /configure/auth + - text: OpenID Connect Plugin + url: /configure/auth/oidc-use-case + items: + - text: OpenID Connect with Curity + url: /configure/auth/oidc-curity + - text: OpenID Connect with Azure AD + url: /configure/auth/oidc-azuread + - text: OpenID Connect with Google + url: /configure/auth/oidc-google + - text: OpenID Connect with Okta + url: /configure/auth/oidc-okta + - text: OpenID Connect with Auth0 + url: /configure/auth/oidc-auth0 + - text: OpenID Connect with Cognito + url: /configure/auth/oidc-cognito + - text: OpenID Connect Plugin Reference + url: /hub/kong-inc/openid-connect + absolute_url: true + - text: Allowing Multiple Authentication Methods + url: /configure/auth/allowing-multiple-authentication-methods + - text: Auth for Kong Manager + url: /configure/auth/kong-manager + items: + - text: Create a Super Admin + url: /configure/auth/kong-manager/super-admin + - text: Configure Networking + url: /configure/auth/kong-manager/networking + - text: Configure Kong Manager to Send Email + url: /configure/auth/kong-manager/email + - text: Reset Passwords and RBAC Tokens + url: /configure/auth/kong-manager/reset-password/ + - text: Configure Workspaces + url: /configure/auth/kong-manager/workspaces + - text: Basic Auth + url: /configure/auth/kong-manager/basic + - text: LDAP + url: /configure/auth/kong-manager/ldap + - text: OIDC + url: /configure/auth/kong-manager/oidc-mapping + - text: Sessions + url: /configure/auth/kong-manager/sessions + + - text: Role-based Access Control (RBAC) + url: /configure/auth/rbac + items: + - text: Add a Role + url: /configure/auth/rbac/add-role + - text: Add a User + url: /configure/auth/rbac/add-user + - text: Add an Admin + url: /configure/auth/rbac/add-admin + - text: Mapping LDAP Service Directory Groups to Kong Roles + url: /configure/auth/service-directory-mapping + - text: Kong Dev Portal + url: /developer-portal/ + items: + - text: Enable the Dev Portal + url: /developer-portal/enable-dev-portal + - text: Structure and File Types + url: /developer-portal/structure-and-file-types + - text: Portal API Documentation + url: /dev-portal/api/v1/ + absolute_url: true + generate: false + - text: Working with Templates + url: /developer-portal/working-with-templates + - text: Using the Editor + url: /developer-portal/using-the-editor + # commented out for now, as this redirects to an old doc version + # - text: Networking + # url: /developer-portal/networking + - text: Configuration + items: + - text: Authentication + items: + - text: Basic Auth + url: /developer-portal/configuration/authentication/basic-auth + - text: Key Auth + url: /developer-portal/configuration/authentication/key-auth + - text: OIDC + url: /developer-portal/configuration/authentication/oidc + - text: Sessions + url: /developer-portal/configuration/authentication/sessions + - text: Adding Custom Registration Fields + url: /developer-portal/configuration/authentication/adding-registration-fields + - text: SMTP + url: /developer-portal/configuration/smtp + - text: Workspaces + url: /developer-portal/configuration/workspaces + - text: Administration + items: + - text: Manage Developers + url: /developer-portal/administration/managing-developers + - text: Developer Roles and Content Permissions + url: /developer-portal/administration/developer-permissions + - text: Application Registration + items: + - text: Authorization Provider Strategy + url: /developer-portal/administration/application-registration/auth-provider-strategy + - text: Enable Application Registration + url: /developer-portal/administration/application-registration/enable-application-registration + - text: Enable Key Authentication for Application Registration + url: /developer-portal/administration/application-registration/enable-key-auth-plugin + - text: External OAuth2 Support + url: /developer-portal/administration/application-registration/3rd-party-oauth + - text: Set up Okta and Kong for external OAuth + url: /developer-portal/administration/application-registration/okta-config + - text: Set Up Azure AD and Kong for External Authentication + url: /developer-portal/administration/application-registration/azure-oidc-config + - text: Manage Applications + url: /developer-portal/administration/application-registration/managing-applications + - text: Customization + items: + - text: Easy Theme Editing + url: /developer-portal/theme-customization/easy-theme-editing + - text: Migrating Templates Between Workspaces + url: /developer-portal/theme-customization/migrating-templates + - text: Markdown Rendering Module + url: /developer-portal/theme-customization/markdown-extended + - text: Customizing Portal Emails + url: /developer-portal/theme-customization/emails + - text: Adding and Using JavaScript Assets + url: /developer-portal/theme-customization/adding-javascript-assets + - text: Single Page App in Dev Portal + url: /developer-portal/theme-customization/single-page-app + - text: Alternate OpenAPI Renderer + url: /developer-portal/theme-customization/alternate-openapi-renderer + - text: Helpers CLI + url: /developer-portal/helpers/cli + + - text: Configure gRPC Plugins + url: /configure/grpc + - text: GraphQL Quickstart + url: /configure/graphql-quickstart + - text: Logging Reference + url: /configure/logging + - text: Network and Firewall + url: /configure/network + +- title: Monitor + icon: /assets/images/icons/documentation/icn-vitals.svg + items: + - text: Kong Vitals + url: /vitals + items: + - text: Metrics + url: /vitals/vitals-metrics + - text: Reports + url: /vitals/vitals-reports + - text: Vitals with InfluxDB + url: /vitals/vitals-influx-strategy + - text: Vitals with Prometheus + url: /vitals/vitals-prometheus-strategy + - text: Estimate Vitals Storage in PostgreSQL + url: /vitals/vitals-estimates + - text: Prometheus plugin + url: /hub/kong-inc/prometheus + absolute_url: true + - text: Zipkin plugin + url: /hub/kong-inc/zipkin + absolute_url: true + +- title: Reference + icon: /assets/images/icons/documentation/icn-references-color.svg + items: + - text: Admin API + url: /admin-api + items: + - text: DB-less Mode + url: /admin-api/#db-less-mode + - text: Declarative Configuration + url: /admin-api/#declarative-configuration + - text: Supported Content Types + url: /admin-api/#supported-content-types + - text: Information Routes + url: /admin-api/#information-routes + - text: Health Routes + url: /admin-api/#health-routes + - text: Tags + url: /admin-api/#tags + - text: Service Object + url: /admin-api/#service-object + - text: Route Object + url: /admin-api/#route-object + - text: Consumer Object + url: /admin-api/#consumer-object + - text: Plugin Object + url: /admin-api/#plugin-object + - text: Certificate Object + url: /admin-api/#certificate-object + - text: CA Certificate Object + url: /admin-api/#ca-certificate-object + - text: SNI Object + url: /admin-api/#sni-object + - text: Upstream Object + url: /admin-api/#upstream-object + - text: Target Object + url: /admin-api/#target-object + - text: Licenses + url: /admin-api/licenses/reference + items: + - text: Licenses Reference + url: /admin-api/licenses/reference + - text: Licenses Examples + url: /admin-api/licenses/examples + - text: Workspaces + url: /admin-api/workspaces/reference + items: + - text: Workspaces Reference + url: /admin-api/workspaces/reference + - text: Workspace Examples + url: /admin-api/workspaces/examples + - text: RBAC + url: /admin-api/rbac/reference + items: + - text: RBAC Reference + url: /admin-api/rbac/reference + - text: RBAC Examples + url: /admin-api/rbac/examples + - text: Admins + url: /admin-api/admins/reference + items: + - text: API Reference + url: /admin-api/admins/reference + - text: Examples + url: /admin-api/admins/examples + - text: Consumer Groups + url: /admin-api/consumer-groups/reference + items: + - text: API Reference + url: /admin-api/consumer-groups/reference + - text: Examples + url: /admin-api/consumer-groups/examples + - text: Event Hooks + url: /admin-api/event-hooks/reference + items: + - text: Event Hooks Reference + url: /admin-api/event-hooks/reference + - text: Examples + url: /admin-api/event-hooks/examples + - text: Audit Logging + url: /admin-api/audit-log + - text: Keyring and Data Encryption + url: /admin-api/db-encryption + - text: Securing the Admin API + url: /admin-api/secure-admin-api + - text: DB-less and Declarative Configuration + url: /reference/db-less-and-declarative-config + - text: Configuration Reference + url: /reference/configuration + - text: CLI Reference + url: /reference/cli + - text: Load Balancing Reference + url: /reference/loadbalancing + - text: Proxy Reference + url: /reference/proxy + - text: Rate Limiting Library + url: /reference/rate-limiting + - text: Health Checks and Circuit Breakers Reference + url: /reference/health-checks-circuit-breakers + - text: Clustering Reference + url: /reference/clustering + + - text: Plugin Development Kit + url: /pdk + items: + - text: kong.client + url: /pdk/kong.client + + - text: kong.client.tls + url: /pdk/kong.client.tls + + - text: kong.cluster + url: /pdk/kong.cluster + + - text: kong.ctx + url: /pdk/kong.ctx + + - text: kong.ip + url: /pdk/kong.ip + + - text: kong.log + url: /pdk/kong.log + + - text: kong.nginx + url: /pdk/kong.nginx + + - text: kong.node + url: /pdk/kong.node + + - text: kong.request + url: /pdk/kong.request + + - text: kong.response + url: /pdk/kong.response + + - text: kong.router + url: /pdk/kong.router + + - text: kong.service + url: /pdk/kong.service + + - text: kong.service.request + url: /pdk/kong.service.request + + - text: kong.service.response + url: /pdk/kong.service.response + + - text: kong.table + url: /pdk/kong.table + + - text: Plugin Development Guide + url: /plugin-development + items: + - text: Introduction + url: /plugin-development + + - text: File structure + url: /plugin-development/file-structure + + - text: Implementing custom logic + url: /plugin-development/custom-logic + + - text: Plugin configuration + url: /plugin-development/plugin-configuration + + - text: Accessing the datastore + url: /plugin-development/access-the-datastore + + - text: Storing custom entities + url: /plugin-development/custom-entities + + - text: Caching custom entities + url: /plugin-development/entities-cache + + - text: Extending the Admin API + url: /plugin-development/admin-api + + - text: Writing tests + url: /plugin-development/tests + + - text: (un)Installing your plugin + url: /plugin-development/distribution + + - text: Plugins in Other Languages + url: /reference/external-plugins + - text: File Permissions Reference + url: /gateway/3.0.x/reference/file-access-permissions + absolute_url: /gateway/3.0.x/reference/file-access-permissions diff --git a/app/_data/kong_versions.yml b/app/_data/kong_versions.yml index b442734adab9..2ceb3e7b4b3a 100644 --- a/app/_data/kong_versions.yml +++ b/app/_data/kong_versions.yml @@ -452,56 +452,15 @@ lua_doc: true - + release: "2.6.x" + ee-version: "2.6.1.0" + ce-version: "2.6.1" + edition: "gateway" +- + release: "2.7.x" + ee-version: "2.7.2.0" + ce-version: "2.7.2" edition: "gateway" -# - -# # Combined Gateway docs (single-sourced) -# release: "2.6.x" -# ee-version: "2.6.1.0" -# ce-version: "2.6.1" -# edition: "gateway" -# luarocks_version: "2.5.1-0" -# dependencies: -# luajit: "2.1.0-beta3" -# luarocks: "3.8.0" -# cassandra: "3.x.x" -# postgres: "9.5+" -# openresty: "1.19.9.1" -# openssl: "1.1.1n" -# libyaml: "0.2.5" -# pcre: "8.44" -# lua_doc: true -# - -# release: "2.7.x" -# ee-version: "2.7.2.0" -# ce-version: "2.7.2" -# edition: "gateway" -# luarocks_version: "2.5.1-0" -# dependencies: -# luajit: "2.1.0-beta3" -# luarocks: "3.8.0" -# cassandra: "3.x.x" -# postgres: "9.5+" -# openresty: "1.19.9.1" -# openssl: "1.1.1n" -# libyaml: "0.2.5" -# pcre: "8.45" -# lua_doc: true -# - -# release: "2.8.x" -# ee-version: "2.8.1.0" -# ce-version: "2.8.1" -# edition: "gateway" -# luarocks_version: "2.5.1-0" -# dependencies: -# luajit: "2.1.0-beta3" -# luarocks: "3.8.0" -# cassandra: "3.x.x" -# postgres: "9.5+" -# openresty: "1.19.9.1" -# openssl: "1.1.1n" -# libyaml: "0.2.5" -# pcre: "8.45" -# lua_doc: true - release: "3.0.x" ee-version: "3.0.0.0" diff --git a/app/enterprise/changelog.md b/app/enterprise/changelog.md index c78c5c1accf9..646c3f4328fc 100644 --- a/app/enterprise/changelog.md +++ b/app/enterprise/changelog.md @@ -1,24 +1,26 @@ --- -title: Kong Gateway Changelog Archive +title: Kong Gateway Enterprise Changelog Archive no_version: true --- -This changelog covers Kong Gateway versions that have reached end of sunset support. +This changelog covers Kong Gateway Enterprise versions that have reached end of sunset support. +For the archives of the combined Kong Gateway Enterprise and Kong Gateway OSS changelog, see the [Kong Gateway changelog for 2.6 onward](/gateway/changelog/). Looking for recent releases? See [https://docs.konghq.com/gateway/changelog/](https://docs.konghq.com/gateway/changelog/) for the latest changes. Archives: -- [Kong Gateway 2.x](#kong-gateway-2x) -- [Kong Gateway 1.x](#kong-gateway-1x) -- [Kong Gateway 0.x](#kong-gateway-0x) +- [Kong Gateway Enterprise 2.x](#kong-gateway-enterprise-2x) +- [Kong Gateway Enterprise 1.x](#kong-gateway-enterprise-1x) +- [Kong Gateway Enterprise 0.x](#kong-gateway-enterprise-0x) --- -## Kong Gateway 2.x +## Kong Gateway Enterprise 2.x -Archived Kong Gateway versions in the 2.x series. +Archived Kong Gateway Enterprise versions in the 2.x series from 2.5 and earlier. +For 2.x versions later than 2.5, see the merged [Kong Gateway changelog](/gateway/changelog/). ## 2.5.1.2 **Release Date:** 2021/11/18 @@ -2433,7 +2435,7 @@ Kong Enterprise 2.1.3.0 version includes 2.1.0.0 (beta) features, fixes, known i * The ability to share an entity between Workspaces is no longer supported. The new method requires a copy of the entity to be created in the other Workspaces. -## Kong Gateway 1.x +## Kong Gateway Enterprise 1.x Archived Kong Gateway versions in the 1.x series. @@ -3351,7 +3353,7 @@ repository will allow you to do both easily. - Fixes: centos and alpine images did not work on some OpenShift setups with relaxed anyuid SCC settings. -## Kong Gateway 0.x +## Kong Gateway Enterprise 0.x Archived Kong Gateway versions in the 0.x series. diff --git a/app/gateway/2.6.x/admin-api/admins/examples.md b/app/gateway/2.6.x/admin-api/admins/examples.md new file mode 100644 index 000000000000..2baf297fe948 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/admins/examples.md @@ -0,0 +1,57 @@ +--- +title: Admins Examples +badge: enterprise +--- + +## How to Invite and Register an Admin + +### Introduction + +Can be used for automation + +### Prerequisites + +```bash +export USERNAME= +export EMAIL= +export WORKSPACE= +export HOST= +export TOKEN=Kong-Admin-Token: +``` + +for example: +```bash +export USERNAME=drogon +export EMAIL=test@test.com +export WORKSPACE=default +export HOST=127.0.0.1:8001 +export ADMIN_TOKEN=Kong-Admin-Token:hunter2 +``` + +May benefit from HTTPie and jq. + +## Step 1 +Extract and store the token from the registration URL, either by manually creating an environment variable or by echoing and piping with `jq`: + +#### Manual method example: + +1. Send a request to the registration URL +```bash +http $HOST/$WORKSPACE/admins/$USERNAME?generate_register_url=true $TOKEN +``` + +2. Copy the response and export as an environment variable, for example: +```bash +export REGISTER_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDUwNjc0NjUsImlkIjoiM2IyNzY3MzEtNjIxZC00ZjA3LTk3YTQtZjU1NTg0NmJkZjJjIn0.gujRDi2pX_E7u2zuhYBWD4MoPFKe3axMAq-AUcORg2g +``` + +#### Programmatic method (requires `jq`): +```bash +REGISTER_TOKEN=$(http $HOST/$WORKSPACE/admins/$USERNAME?generate_register_url=true $TOKEN | jq .token -r) +``` + +## Step 2 + +```bash +http $HOST/$WORKSPACE/admins/register token=$REGISTER_TOKEN username=$USERNAME email=$EMAIL password="" +``` diff --git a/app/gateway/2.6.x/admin-api/admins/reference.md b/app/gateway/2.6.x/admin-api/admins/reference.md new file mode 100644 index 000000000000..8a9956f71cad --- /dev/null +++ b/app/gateway/2.6.x/admin-api/admins/reference.md @@ -0,0 +1,327 @@ +--- +title: Admins Reference +badge: enterprise +--- + +## List Admins +**Endpoint** + +
/admins
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [{ + "created_at": 1556638385, + "id": "665b4070-541f-48bf-82c1-53030babaa81", + "updated_at": 1556638385, + "status": 4, + "username": "test-admin", + "email": "test@test.com", + "rbac_token_enabled": true + }, { + "created_at": 1556563122, + "id": "a93ff120-9e6c-4198-b47e-f779104c7eac", + "updated_at": 1556563122, + "status": 0, + "username": "kong_admin", + "rbac_token_enabled": false + }], + "next": null +} +``` + +## Invite an Admin +**Endpoint** + +
/admins
+ +| Attribute | Description | +|-------------|------------------------------------------------------------| +| `email` | The **Admin**'s email address | +| `username` | The **Admin**'s username | +| `custom_id`
optional | The **Admin**'s custom ID | +| `rbac_token_enabled` | Allows the **Admin** to use and reset their RBAC token; `true` by default | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "admin": { + "created_at": 1556638641, + "id": "8f0a742f-07f3-49e0-90d7-4fc7eea7e6a4", + "updated_at": 1556638641, + "status": 4, + "username": "test-case-3", + "email": "test3@test.com", + "rbac_token_enabled": true + } +} +``` + +## Register an Admin's Credentials +**Endpoint** + +
/admins/register
+ +| Attribute | Description | +|-------------|---------------------------| +| `token` | The authentication token | +| `username` | The **Admin**'s username | +| `email` | The **Admin**'s email address | +| `password` | The **Admin**'s new password | + +**Response** + +``` +HTTP 201 Created +``` + +## Send a Password-Reset Email to an Admin +**Endpoint** + +
/admins/password_resets
+ +| Attribute | Description | +|-------------|------------------------------------------------------------| +| `email` | The **Admin**'s email address | + +**Response** + +``` +HTTP 201 Created +``` + +## Reset an Admin's Password +**Endpoint** + +
/admins/password_resets
+ +| Attribute | Description | +|-------------|------------------------------------------------------------| +| `email` | The **Admin**'s email address | +| `password` | The **Admin**'s new password | +| `token` | The authentication token | + +**Response** + +``` +HTTP 200 OK +``` + +## Retrieve an Admin +**Endpoint** + +
/admins/{name_or_id}
+ +| Attribute | Description | +|------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | +| `generate_register_url`
optional | `true` returns a unique registration URL for the **Admin** | + +**Notes:** +* `generate_register_url` will only generate a URL if the **Admin**'s +invitation status is 4 ("invited"). +* `generate_register_url` will override the previous registration URL +for the particular **Admin** each time it is requested. + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1556638385, + "id": "665b4070-541f-48bf-82c1-53030babaa81", + "updated_at": 1556638385, + "status": 4, + "username": "test-admin", + "email": "test@test.com", + "rbac_token_enabled": true +} +``` + +## Update an Admin +**Endpoint** + +
/admins/{name_or_id}
+ +| Attribute | Description | +|----------------------|--------------------------------------------| +| `name_or_id` | The **Admin**'s current username or custom ID | +| `email`
optional | The **Admin**'s new email address | +| `username`
optional | The **Admin**'s new username | +| `custom_id`
optional | The **Admin**'s new custom ID | +| `rbac_token_enabled` | Allows the **Admin** to use and reset their RBAC token; `true` by default | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1556638385, + "id": "665b4070-541f-48bf-82c1-53030babaa81", + "updated_at": 1556639017, + "status": 4, + "username": "test-renamed", + "email": "test@test.com" + "rbac_token_enabled": true +} +``` + +## Delete an Admin +**Endpoint** + +
/admins/{name_or_id}
+ +| Attribute | Description | +|--------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | + +**Response** + +``` +HTTP 204 No Content +``` + +## List an Admin's Roles +**Endpoint** + +
/admins/{name_or_id}/roles
+ +| Attribute | Description | +|--------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "roles": [{ + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1556563122, + "id": "7574eb1d-c9fa-46a9-bd3a-3f1b4b196287", + "name": "read-only", + "is_default": false + }, { + "comment": "Full access to all endpoints, across all workspaces—except RBAC Admin API", + "created_at": 1556563122, + "id": "7fdea5c8-2bfa-4aa9-9c21-7bb9e607186d", + "name": "admin", + "is_default": false + }] +} +``` + +## Create or Update an Admin's Roles +**Endpoint** + +
/admins/{name_or_id}/roles
+ +| Attribute | Description | +|--------------|-----------------------------------------------------------| +| `name_or_id` | The **Admin**'s current username or ID | +| `roles` | (comma separated) string of names of Roles to create or update for an **Admin** | + +**Response** + +``` +HTTP 201 OK +``` + + +```json +{ + "roles": [{ + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1556563122, + "id": "7574eb1d-c9fa-46a9-bd3a-3f1b4b196287", + "name": "read-only", + "is_default": false + }, { + "comment": "Full access to all endpoints, across all workspaces—except RBAC Admin API", + "created_at": 1556563122, + "id": "7fdea5c8-2bfa-4aa9-9c21-7bb9e607186d", + "name": "admin", + "is_default": false + }, { + "comment": "Full access to all endpoints, across all workspaces", + "created_at": 1556563122, + "id": "99bd8d18-f5b6-410e-aefe-d75f4252f13c", + "name": "super-admin", + "is_default": false + }] +} +``` + +## Delete an Admin's Role +**Endpoint** + +
/admins/{name_or_id}/roles
+ +| Attribute | Description | +|--------------|-----------------------------------------------------------| +| `name_or_id` | The **Admin**'s current username or custom ID | +| `roles` | (comma separated) string of names of Roles to remove from an **Admin** | + +**Response** + +``` +HTTP 204 No Content +``` + +## List an Admin's Workspaces +**Endpoint** + +
/admins/{name_or_id}/workspaces
+ +| Attribute | Description | +|--------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | + +**Response** + +``` +HTTP 200 OK +``` + +```json +[{ + "created_at": 1556563122, + "config": { + "portal": true, + "portal_auto_approve": true + }, + "id": "00000000-0000-0000-0000-000000000000", + "name": "default", + "meta": {} +}, { + "created_at": 1556570807, + "config": { + "portal": true + }, + "id": "57b3ce24-6d29-427f-af13-15bd60430e56", + "name": "sdfgsdfg", + "meta": { + "color": "#3894f0" + } +}] +``` diff --git a/app/gateway/2.6.x/admin-api/audit-log.md b/app/gateway/2.6.x/admin-api/audit-log.md new file mode 100644 index 000000000000..790597e544e4 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/audit-log.md @@ -0,0 +1,496 @@ +--- +title: Admin API Audit Log +badge: enterprise +--- + +{{site.base_gateway}} provides a granular logging facility on its Admin API. This +allows cluster administrators to keep detailed track of changes made to the +cluster configuration throughout its lifetime, aiding in compliance efforts and +providing valuable data points during forensic investigations. Generated audit +log trails are [Workspace](/gateway/{{page.release}}/admin-api/workspaces/reference/) and [RBAC](/gateway/{{page.release}}/admin-api/rbac/reference/)-aware, +providing Kong operators a deep and wide look into changes happening within +the cluster. + +## Getting Started + +Audit logging is disabled by default. It is configured via the Kong configuration (e.g. `kong.conf`): + +```bash +audit_log = on # audit logging is enabled +audit_log = off # audit logging is disabled +``` + +or via environment variables: + +```bash +export KONG_AUDIT_LOG=on +export KONG_AUDIT_LOG=off +``` + +As with other Kong configurations, changes take effect on `kong reload` or `kong +restart`. + +## Request Audits + +### Generating and Viewing Audit Logs + +Audit logging provides granular details of each HTTP request that was handled by +Kong's Admin API. Audit log data is written to Kong's back database. As a result, +request audit logs are available via the Admin API (in addition to via direct +database query). For example, consider a query to the Admin API to the `/status` +endpoint: + +``` +vagrant@ubuntu-xenial:/kong$ http :8001/status +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:32:47 GMT +Server: kong/0.34-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: ZuUfPfnxNn7D2OTU6Xi4zCnQkavzMUNM + +{ + "database": { + "reachable": true + }, + "server": { + "connections_accepted": 1, + "connections_active": 1, + "connections_handled": 1, + "connections_reading": 0, + "connections_waiting": 0, + "connections_writing": 1, + "total_requests": 1 + } +} +``` + +The above interaction with the Admin API generates a correlating entry in +the audit log table. Querying the audit log via Admin API returns the details of the interaction above: + +``` +http :8001/audit/requests +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:35:24 GMT +Server: kong/0.34-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: VXgMG1Y3rZKbjrzVYlSdLNPw8asVwhET + +{ + "data": [ + { + "client_ip": "127.0.0.1", + "method": "GET", + "path": "/status", + "payload": null, + "request_id": "ZuUfPfnxNn7D2OTU6Xi4zCnQkavzMUNM", + "request_timestamp": 1581617463, + "signature": null, + "status": 200, + "ttl": 2591995, + "workspace": "0da4afe7-44ad-4e81-a953-5d2923ce68ae" + } + ], + "total": 1 +} +``` + +Note the value of the `request_id` field. This is tied to the +`X-Kong-Admin-Request-ID` response header received in the first transaction. +This allows close association of client requests and audit log records within +the Kong cluster. + +Because every audit log entry is made available via Kong's Admin API, it is +possible to transport audit log entries into existing logging warehouses, SIEM +solutions, or other remote services for duplication and inspection. + +### Workspaces and RBAC + +Audit log entries are written with an awareness of the requested Workspace, and +the RBAC user (if present). When RBAC is enforced, the RBAC user's UUID will be +written to the `rbac_user_id` field in the audit log entry: + +``` +{ + "data": [ + { + "client_ip": "127.0.0.1", + "method": "GET", + "path": "/status", + "payload": null, + "rbac_user_id": "2e959b45-0053-41cc-9c2c-5458d0964331", + "request_id": "QUtUa3RMbRLxomqcL68ilOjjl68h56xr", + "request_timestamp": 1581617463, + "signature": null, + "status": 200, + "ttl": 2591995, + "workspace": "0da4afe7-44ad-4e81-a953-5d2923ce68ae" + } + ], + "total": 1 +} +``` + +Note also the presence of the `workspace` field. This is the UUID of the Workspace with which the request was associated. + +### Limiting Audit Log Generation + +It may be desirable to ignore audit log generation for certain Admin API +requests such as innocuous requests to the `/status` endpoint for +health checking or to ignore requests for a given path prefix (e.g. a given +Workspace). To this end, the `audit_log_ignore_methods` and +`audit_log_ignore_paths` configuration options are presented: + +```bash +audit_log_ignore_methods = GET,OPTIONS +# do not generate an audit log entry for GET or OPTIONS HTTP requests +audit_log_ignore_paths = /foo,/status,^/services,/routes$,/one/.+/two,/upstreams/ +# do not generate an audit log entry for requests that match the above regular expressions +``` + +The values of `audit_log_ignore_paths` are matched via a Perl-compatible regular expression. + +For example, when `audit_log_ignore_paths = /foo,/status,^/services,/routes$,/one/.+/two,/upstreams/`, the following request paths do not generate an audit-log entry in the database: + +- `/status` +- `/status/` +- `/foo` +- `/foo/` +- `/services` +- `/services/example/` +- `/one/services/two` +- `/one/test/two` +- `/routes` +- `/plugins/routes` +- `/one/routes/two` +- `/upstreams/` +- `bad400request` + +The following request paths generate an audit log entry in the database: + +- `/example/services` +- `/routes/plugins` +- `/one/two` +- `/routes/` +- `/upstreams` + +### Audit Log Retention + +Request audit records are kept in the database for a duration defined by the +`audit_log_record_ttl` [Kong configuration property](/gateway/{{page.release}}/reference/configuration/#audit_log_record_ttl). +Records in the database older than `audit_log_record_ttl` seconds are automatically +purged. In Cassandra databases, record deletion is handled automatically via the +Cassandra TTL mechanism. In PostgreSQL databases, records are purged via the stored +procedure that is executed on insert into the record database. Thus, request +audit records may exist in the database longer than the configured TTL, if no new +records are inserted to the audit table following the expiration timestamp. + +## Database Audits + +### Generating and Viewing Audit Logs + +In addition to Admin API request data, Kong will generate granular audit log +entries for all insertions, updates, and deletions to the cluster database. +Database update audit logs are also associated with Admin API request unique +IDs. Consider the following request to create a Consumer: + +``` +http :8001/consumers username=bob +HTTP/1.1 201 Created +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:50:18 GMT +Server: kong/0.34-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: 59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2 + +{ + "created_at": 1542131418000, + "id": "16787ed7-d805-434a-9cec-5e5a3e5c9e4f", + "type": 0, + "username": "bob" +} + +``` + +As seen before, a request audit log is generated with details about the request. +Note the presence of the `payload` field, recorded when the request body is +present: + +``` +http :8001/audit/requests +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:52:41 GMT +Server: kong/0.34-dev-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: SpPaxLTkDNndzKaYiWuZl3xrxDUIiGRR + +{ + "data": [ + { + "client_ip": "127.0.0.1", + "method": "POST", + "path": "/consumers", + "payload": "{\"username\": \"bob\"}", + "request_id": "59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2", + "request_timestamp": 1581617463, + "signature": null, + "status": 201, + "ttl": 2591995, + "workspace": "fd51ce6e-59c0-4b6b-b991-aa708a9ff4d2" + } + ], + "total": 1 +} +``` + +Additionally, audit logs are generated to track the creation of the +database entity: + +``` +http :8001/audit/objects +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:53:27 GMT +Server: kong/0.34-dev-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: ZKra3QT0d3eJKl96jOUXYueLumo0ck8c + +{ + "data": [ + { + "dao_name": "consumers", + "entity": "{\"created_at\":1542131418000,\"id\":\"16787ed7-d805-434a-9cec-5e5a3e5c9e4f\",\"username\":\"bob\",\"type\":0}", + "entity_key": "16787ed7-d805-434a-9cec-5e5a3e5c9e4f", + "expire": 1544723418009, + "id": "7ebabee7-2b09-445d-bc1f-2092c4ddc4be", + "operation": "create", + "request_id": "59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2", + "request_timestamp": 1581617463, + }, + ], + "total": 1 +} +``` + +Object audit entries contain information about the entity updated, including the +entity body itself, its database primary key, and the type of operation +performed (`create`, `update`, or `delete`). Note also the associated + `request_id` field. + +### Limiting Audit Log Generation + +As with request audit logs, it may be desirable to skip generation of audit logs +for certain database tables. This is configurable via the +`audit_log_ignore_tables` Kong config option: + +``` +audit_log_ignore_tables = consumers +# do not generate database audit logs for changes to the consumers table +``` + +### Audit Log Retention + +Database audit records are kept in the database for a duration defined by the +`audit_log_record_ttl` [Kong configuration property](/gateway/{{page.release}}/reference/configuration/#audit_log_record_ttl). +Records in the database older than `audit_log_record_ttl` seconds are automatically +purged. In Cassandra databases, record deletion is handled automatically via the +Cassandra TTL mechanism. In PostgreSQL databases, records are purged via the stored +procedure that is executed on insert into the record database. Thus, database +audit records may exist in the database longer than the configured TTL, if no new +records are inserted to the audit table following the expiration timestamp. + +## Digital Signatures + +To provide non-repudiation, audit logs may be signed with a private RSA key. When +enabled, a lexically sorted representation of each audit log entry is signed by +the defined private key; the signature is stored in an additional field within +the record itself. The public key should be stored elsewhere and can be used +later to validate the signature of the record. + +### Setting Up Log Signing + +Generate a private key via the `openssl` tool: + +```bash +openssl genrsa -out private.pem 2048 +``` + +Extract the public key for future audit verification: + +``` +openssl rsa -in private.pem -outform PEM -pubout -out public.pem +``` + +Configure Kong to sign audit log records: + +``` +audit_log_signing_key = /path/to/private.pem +``` + +Audit log entries will now contain a field `signature`: + +``` +{ + "client_ip": "127.0.0.1", + "method": "GET", + "path": "/status", + "payload": null, + "request_id": "Ka2GeB13RkRIbMwBHw0xqe2EEfY0uZG0", + "request_timestamp": 1581617463, + "signature": "l2LWYaRIHfXglFa5ehFc2j9ijfERazxisKVtJnYa+QUz2ckcytxfOLuA4VKEWHgY7cCLdn5C7uRJzE6es5V2SoOV59NOpskkr5lTt9kzao64UEw5UNOdeZYZKwyhG9Ge7IsxTK6haW0iG3a9dHqlKlwvnHZTbFM8TUV/umg8sJ1QJ/5ivXecbyHYtD5luKAI6oEgIdZPtQexRkwxlzvfR8lzeC/dDc2slSrjWRbBxNFlgfRKhDdVzVzgu8pEucgKggu67PKLkJ+bQEkxX1+Yg3czIpJyC3t6cgoggb0UNtBq1uUpswe0wdueKh6G5Gzz6XrmOjlv7zSz4gtVyEHZgg==", + "status": 200, + "ttl": 2591995, + "workspace": "fd51ce6e-59c0-4b6b-b991-aa708a9ff4d2" +} +``` + +### Validating Signatures + +To verify record signatures, use the `openssl` utility, or other cryptographic +tools that are capable of validating RSA digital signatures. + +Signatures are generated using a 256-bit SHA digest. The following example +demonstrates how to verify the audit log record shown above. First, store the +record signature on disk after stripping the Base64 +encoding: + +```bash +cat < record_signature +> l2LWYaRIHfXglFa5ehFc2j9ijfERazxisKVtJnYa+QUz2ckcytxfOLuA4VKEWHgY7cCLdn5C7uRJzE6es5V2SoOV59NOpskkr5lTt9kzao64UEw5UNOdeZYZKwyhG9Ge7IsxTK6haW0iG3a9dHqlKlwvnHZTbFM8TUV/umg8sJ1QJ/5ivXecbyHYtD5luKAI6oEgIdZPtQexRkwxlzvfR8lzeC/dDc2slSrjWRbBxNFlgfRKhDdVzVzgu8pEucgKggu67PKLkJ+bQEkxX1+Yg3czIpJyC3t6cgoggb0UNtBq1uUpswe0wdueKh6G5Gzz6XrmOjlv7zSz4gtVyEHZgg== +> EOF +``` + +Next, the audit record must be transformed into its canonical format used for +signature generation. This transformation requires serializing the record into +a string format that can be verified. The format is a lexically-sorted, +pipe-delimited string of each audit log record part, _without_ the `signature`, +`ttl`, or `expire` fields. The following is a canonical +implementation written in Lua: + +```lua +local cjson = require "cjson" +local pl_sort = require "pl.tablex".sort + +local function serialize(data) + local p = {} + + data.signature = nil + data.expire = nil + data.ttl = nil + + for k, v in pl_sort(data) do + if type(v) == "table" then + p[#p + 1] = serialize(v) + elseif v ~= cjson.null then + p[#p + 1] = v + end + end + + return p +end + +table.concat(serialize(data), "|") +``` + +For example, the canonical format of the audit record above is: + +``` +cat canonical_record.txt +127.0.0.1|1544724298663|GET|/status|Ka2GeB13RkRIbMwBHw0xqe2EEfY0uZG0|1542132298664|200|fd51ce6e-59c0-4b6b-b991-aa708a9ff4d2 +``` + +{:.note} +> Ensure that the contents of the canonical record file on disk match the expected +canonical record format exactly. The presence of any additional bytes, such as +a trailing newline `\n`, will cause a validation failure in the next step. + +Once these two elements are in place, the signature can be verified: + +```bash +openssl dgst -sha256 -verify public.pem -signature record_signature canonical_record.txt +Verified OK +``` + +--- + +## Reference + +### API Reference + +#### List Request Audit Logs + +##### Endpoint + +
/audit/requests
+ +##### Response + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "client_ip": "127.0.0.1", + "method": "GET", + "path": "/status", + "payload": null, + "request_id": "ZuUfPfnxNn7D2OTU6Xi4zCnQkavzMUNM", + "request_timestamp": 1581617463, + "signature": null, + "status": 200, + "ttl": 2591995, + "workspace": "0da4afe7-44ad-4e81-a953-5d2923ce68ae" + } + ], + "total": 1 +} +``` + +#### List Database Audit Logs + +##### Endpoint + +
/audit/objects
+ +##### Response + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "dao_name": "consumers", + "entity": "{\"created_at\":1542131418000,\"id\":\"16787ed7-d805-434a-9cec-5e5a3e5c9e4f\",\"username\":\"bob\",\"type\":0}", + "entity_key": "16787ed7-d805-434a-9cec-5e5a3e5c9e4f", + "expire": 1544723418009, + "id": "7ebabee7-2b09-445d-bc1f-2092c4ddc4be", + "operation": "create", + "request_id": "59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2" + }, + ], + "total": 1 +} +``` + +### Configuration Reference + +See the [Data & Admin Audit](/gateway/{{page.release}}/reference/configuration/#data--admin-audit) +section of the Configuration Property Reference. diff --git a/app/gateway/2.6.x/admin-api/db-encryption.md b/app/gateway/2.6.x/admin-api/db-encryption.md new file mode 100644 index 000000000000..0acbe9ab129c --- /dev/null +++ b/app/gateway/2.6.x/admin-api/db-encryption.md @@ -0,0 +1,169 @@ +--- +title: Keyring & Data Encryption +badge: enterprise +--- + +## View Keyring +**Endpoint** + +
/keyring
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "active": "RfsDJ2Ol", + "ids": [ + "RfsDJ2Ol", + "xSD219lH" + ] +} + +``` + +## View Active Key +**Endpoint** + +
/keyring/active
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "id": "RfsDJ2Ol" +} + +``` + +## Export Keyring + +*This endpoint is only available with the `cluster` keyring strategy.* + +*The endpoint requires that the `keyring_public_key` and `keyring_private_key` Kong configuration values are defined.* + +**Endpoint** + +
/keyring/export
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": "..." +} +``` + +## Import Exported Keyring + +*This endpoint is only available with the `cluster` keyring strategy.* + +*The endpoint requires that the `keyring_public_key` and `keyring_private_key` Kong configuration values are defined.* + +**Endpoint** + +
/keyring/import
+ +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `data` | Base64-encoded keyring export material. | + + +**Response** + +``` +HTTP 201 Created +``` + +## Import Key + +*This endpoint is only available with the `cluster` keyring strategy.* + +*The endpoint requires that the `keyring_public_key` and `keyring_private_key` Kong configuration values are defined.* + +**Endpoint** + +
/keyring/import/raw
+ +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `key` | 8-byte key identifier. | +| `data` | Base64-encoded keyring export material. | + + +**Response** + +``` +HTTP 201 Created +``` + +## Generate New Key + +*This endpoint is only available with the `cluster` keyring strategy.* + +**Endpoint** + +
/keyring/generate
+ +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "id": "500pIquV", + "key": "3I23Ben5m7qKcCA/PK7rnsNeD3kI4IPtA6ki7YjAgKA=" +} +``` + +## Remove Key from Keyring + +*This endpoint is only available with the `cluster` keyring strategy.* + +**Endpoint** + +
/keyring/remove
+ +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `key` | 8-byte key identifier. | + + +**Response** + +``` +HTTP 204 No Content +``` + +## Sync Keyring with Vault Endpoint + +*This endpoint is only available with the `vault` keyring strategy.* + +**Endpoint** + +
/keyring/vault/sync
+ +**Response** + +``` +HTTP 204 No Content +``` diff --git a/app/gateway/2.6.x/admin-api/event-hooks/examples.md b/app/gateway/2.6.x/admin-api/event-hooks/examples.md new file mode 100644 index 000000000000..69a57ce5d7cb --- /dev/null +++ b/app/gateway/2.6.x/admin-api/event-hooks/examples.md @@ -0,0 +1,389 @@ +--- +title: Event Hooks Examples +badge: enterprise +--- + +{% include_cached /md/enterprise/event-hooks-intro.md %} + +## Webhook + +Webhook event hooks make JSON POST requests to a provided URL with the event data as a payload. +For this example, we will use a site that is helpful for testing webhooks: [https://webhook.site](https://webhook.site). + +To create a webhook event hook: + +1. Generate a URL by navigating to [https://webhook.site](https://webhook.site) in your web browser. +2. Select **Copy to clipboard** next to **Your unique URL**. +3. Create a webhook event hook on the `consumers` event (Kong entity the event hook will listen to for events), + on the `crud` source (action that triggers logging), and the URL you copied from step 2 using the following HTTP request: +{% capture the_code %} +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/event-hooks \ +-d source=crud \ +-d event=consumers \ +-d handler=webhook \ +-d config.url= +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/event-hooks \ +source=crud \ +event=consumers \ +handler=webhook \ +config.url= +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code | indent }} + +4. Navigate to the URL from step 2. You should see a POST request, of type `ping`, notifying our webhook endpoint + about the creation of this webhook. +5. In Kong Manager or Kong Admin API, add a consumer from any workspace. + +{% capture the_code2 %} +{% navtabs %} +{% navtab Kong Manager %} + +1. Select the workspace. +2. Select **Consumers** in the left navigation. +3. Select the **New Consumer** button. +4. Enter a **Username**. +5. (Optional) Enter a **Custom ID** and any **Tags**. +6. Select the **Create** button. + +{% endnavtab %} +{% navtab Admin API %} + +Create a consumer, Ada Lovelace, by making the following HTTP request to your instance of the Kong Admin API: + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers \ +-d username="Ada Lovelace" +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/consumers \ +username="Ada Lovelace" +``` +{% endnavtab %} +{% endnavtabs %} + +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code2 | indent }} + +6. Check the URL from the [https://webhook.site](https://webhook.site) page. + You should see an entry with data for the new consumer in its payload. + + ```json + { + "source": "crud", + "entity": { + "created_at": 1627581878, + "type": 0, + "username": "Ada Lovelace", + "id": "0fd2319f-13ea-4582-a448-8d11893026a8" + }, + "event": "consumers", + "operation": "create", + "schema": "consumers" + } + ``` + +## Custom webhook + +Custom webhook event hooks are fully customizable requests. Custom webhooks are useful for building direct +integration with a service. Because custom webhooks are fully configurable, they have more complex configurations. +Custom webhooks support Lua templating on a configurable body, form payload, and headers. For a list of +possible fields for templating, see the [sources](/gateway/{{ page.release }}/admin-api/event-hooks/reference/#list-all-sources) endpoint. + +The following example sends a message to Slack any time a new administrator is invited to {{site.base_gateway}}. +Slack allows for [incoming webhooks](https://slack.com/help/articles/115005265063-Incoming-webhooks-for-Slack#set-up-incoming-webhooks) +and we can use these to build an integration with Kong's event hooks features. + +To create a custom webhook event hook: + +1. [Create an app in Slack.](https://api.slack.com/apps?new_app=1) +2. Activate incoming webhooks in the settings for your new app. +3. Select to **Add New Webhook to Workspace**, select the channel where you wish to receive notices, and select **Allow**. +4. Copy the **Webhook URL**, for example `https://hooks.slack.com/services/foo/bar/baz`. +5. Create a webhook event hook on the `admins` event (Kong entity the event hook will listen to for events), + and the `crud` source (action that triggers logging), and format the payload as, {% raw %}"Admin account \`{{ entity.username }}\` {{ operation }}d; e-mail address set to \`{{ entity.email }}\`"{% endraw %}, using the following HTTP request: + +{% capture the_code3 %} +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/event-hooks \ +-d source=crud \ +-d event=admins \ +-d handler=webhook-custom \ +-d config.method=POST \ +-d config.url= \ +-d config.headers.content-type="application/json" \ +-d config.payload.text={% raw %}"Admin account \`{{ entity.username }}\` {{ operation}}d; email address set to \`{{ entity.email }}\`"{% endraw %} +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/event-hooks \ +source=crud \ +event=admins \ +handler=webhook-custom \ +config.method=POST \ +config.url= \ +config.headers.content-type="application/json" \ +config.payload.text={% raw %}"Admin account \`{{ entity.username }}\` {{ operation}}d; email address set to \`{{ entity.email }}\`"{% endraw %} +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code3 | indent }} + +6. Turn on RBAC. + +{% capture anInclude %} +{% include_cached /md/enterprise/turn-on-rbac.md %} +{% endcapture %} +{{ anInclude | indent }} + +7. Invite an Admin using Kong Manager or the Kong Admin API. + +{% capture the_code2 %} +{% navtabs %} +{% navtab Kong Manager %} + +1. Go to Kong Manager, or reload the page if you already have it open and you will see a login screen. +2. Log in to Kong Manager with the built-in Super Admin account, `kong_admin`, and its password. + This is the initial `KONG_PASSWORD` you used when you ran migrations during installation. +3. From the **Teams > Admins** tab, click **Invite Admin**. +4. Enter the new administrator's **Email** address and **Username**. +5. Click **Invite Admin** to send the invite. + At this point in the getting started guide, you likely haven’t set up SMTP yet, so no email will be sent. + +{% endnavtab %} +{% navtab Admin API %} + +Create an admin, Arya Stark, by making the following HTTP request to your instance of the Kong Admin API: + +{:.note} +> **Note:** Replace `` with your `kong_admin` password. This is the initial + `KONG_PASSWORD` you used when you ran migrations during installation. + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/admins \ +-d username="Arya Stark" \ +-d email=arya@gameofthrones.com \ +-H Kong-Admin-Token: +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/admins \ +username="Arya Stark" \ +email=arya@gameofthrones.com \ +Kong-Admin-Token= +``` +{% endnavtab %} +{% endnavtabs %} + +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code2 | indent }} + +Afterwards, you should receive a message in the Slack channel you selected with the message you included as the +`config.payload.text`. + +## Log + +Log event hooks log the specified event and content of the payload into the {{site.base_gateway}} logs. + +To create a log event hook: + +1. Create a log event hook on the `consumers` event (Kong entity the event hook will listen to for events) + and on the `crud` source (action that triggers logging) using the following HTTP request: + +{% capture the_code5 %} +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/event-hooks \ +-d source=crud \ +-d event=consumers \ +-d handler=log +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/event-hooks \ +source=crud \ +event=consumers \ +handler=log +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code5 | indent }} + +2. In Kong Manager or Kong Admin API, add a consumer from any workspace. + +{% capture the_code6 %} +{% navtabs %} +{% navtab Kong Manager %} + +1. Select the workspace. +2. Select **Consumers** in the left navigation. +3. Select the **New Consumer** button. +4. Enter a **Username**. +5. (Optional) Enter a **Custom ID** and any **Tags**. +6. Select the **Create** button. + +{% endnavtab %} +{% navtab Admin API %} + +Create a consumer, Elizabeth Bennet, by making the following HTTP request to your instance of the Kong Admin API: + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers \ +-d username="Elizabeth Bennet" +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/consumers \ +username="Elizabeth Bennet" +``` +{% endnavtab %} +{% endnavtabs %} + +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code6 | indent }} + +3. You should see an entry with data for the new consumer in the payload in Kong's error log, + which is typically accessible at `/usr/local/kong/logs/error.log`. + + ```log + 172.19.0.1 - - [29/Jul/2021:15:57:15 +0000] "POST /consumers HTTP/1.1" 409 147 "-" "HTTPie/2.4.0" + 2021/07/29 15:57:26 [notice] 68854#0: *819021 +--------------------------------------------------+, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 |[kong] event_hooks.lua:?:452 "log callback: " { "consumers", "crud", {|, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | entity = { |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | created_at = 1627574246, |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | id = "4757bd6b-8d54-4b08-bf24-01e346a9323e",|, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | type = 0, |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | username = "Elizabeth Bennet" |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | }, |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | operation = "create", |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | schema = "consumers" |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | }, 68854 } |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 +--------------------------------------------------+, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + + ``` + +## Lambda + +The lambda event hook allows you to write completely custom logic in Lua code and +hook it into a variety of Kong events. The following example writes a log entry +any time a consumer changes, but conditionally and with custom formatting. + +{:.important} +> The lambda event hook type is extremely powerful: you can write completely custom logic to handle any use case you want. +However, it’s [restricted by default through the sandbox.](/gateway/{{ page.release }}/reference/configuration/#untrusted_lua). This +sandbox is put in place to keep users safe: it’s easy to inadvertently add unsafe libraries/objects into the sandbox +and leave the {{site.base_gateway}} exposed to security vulnerabilities. Use caution before modifying these sandbox settings. + +To create a lambda event hook: + +1. Create a Lua script to load into the lambda event hook and save it to a file named `lambda.lua` on your home directory. + + ```lua + return function (data, event, source, pid) + local user = data.entity.username + error("Event hook on consumer " .. user .. "") + end + ``` +2. Create a lambda event hook on the `consumers` event (Kong entity the event hook will listen to for events) + and on the `crud` source (action that triggers logging) using the following HTTP request: + +{% capture the_code7 %} +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/event-hooks \ +-d source=crud \ +-d event=consumers \ +-d handler=lambda \ +-F config.functions='return function (data, event, source, pid) local user = data.entity.username error("Event hook on consumer " .. user .. "")end' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/event-hooks \ +source=crud \ +event=consumers \ +handler=lambda \ +config.functions[]=@~/lambda.lua +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code7 | indent }} + +3. In Kong Manager or Kong Admin API, add a consumer to any workspace. + +{% capture the_code8 %} +{% navtabs %} +{% navtab Kong Manager %} + +1. Select the workspace. +2. Select **Consumers** in the left navigation. +3. Select the **New Consumer** button. +4. Enter a **Username**. +5. (Optional) Enter a **Custom ID** and any **Tags**. +6. Select the **Create** button. + +{% endnavtab %} +{% navtab Admin API %} + +Create a consumer, Lois Lane, by making the following HTTP request to your instance of the Kong Admin API: + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers \ +-d username="Lois Lane" +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/consumers \ +username="Lois Lane" +``` +{% endnavtab %} +{% endnavtabs %} + +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code8 | indent }} + +3. You should see an entry "Event hook on consumer Lois Lane" in Kong's error log, + which is typically accessible at `/usr/local/kong/logs/error.log`. + + ```log + 2021/07/29 21:52:54 [error] 114#0: *153047 [kong] event_hooks.lua:190 [string "return function (data, event, source, pid)..."]:3: Event hook on consumer Lois Lane, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + ``` diff --git a/app/gateway/2.6.x/admin-api/event-hooks/reference.md b/app/gateway/2.6.x/admin-api/event-hooks/reference.md new file mode 100644 index 000000000000..e4903e85f248 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/event-hooks/reference.md @@ -0,0 +1,427 @@ +--- +title: Event Hooks Reference +badge: enterprise +--- + +{:.important} +> **Important:** Before you can use event hooks for the first time, Kong needs to be +reloaded. + +{% include_cached /md/enterprise/event-hooks-intro.md %} + +{:.note} +> **Note:** Event hooks do not work with {{site.konnect_short_name}} yet. + +## List all event hooks + +**Endpoint** + +
/event-hooks
+ +**Response** + +```json +{ + "data": [ + { + "config": { + "body": null, + "body_format": true, + "headers": { + "content-type": "application/json" + }, + "headers_format": false, + "method": "POST", + "payload": { + "text": "{% raw %}Admin account \`{{ entity.username }}\` {{ operation}}d; email address set to \`{{ entity.email }}\`{% endraw %}" + }, + "payload_format": true, + "secret": null, + "ssl_verify": false, + "url": "https://hooks.slack.com/services/foo/bar/baz" + }, + "created_at": 1627588552, + "event": "admins", + "handler": "webhook-custom", + "id": "937df175-3db2-4e6d-8aa1-d95c94a76089", + "on_change": null, + "snooze": null, + "source": "crud" + }, + { + "config": { + "headers": {}, + "secret": null, + "ssl_verify": false, + "url": "https://webhook.site/a1b2c3-d4e5-g6h7-i8j9-k1l2m3n4o5p6" + }, + "created_at": 1627581575, + "event": "consumers", + "handler": "webhook", + "id": "c57340ab-9fed-40fd-bb7e-1cef8d37c2df", + "on_change": null, + "snooze": null, + "source": "crud" + }, + { + "config": { + "functions": [ + "return function (data, event, source, pid)\n local user = data.entity.username\n error(\"Event hook on consumer \" .. user .. \"\")\nend\n" + ] + }, + "created_at": 1627595513, + "event": "consumers", + "handler": "lambda", + "id": "c9fdd58d-5416-4d3a-9467-51e5cfe4ca0e", + "on_change": null, + "snooze": null, + "source": "crud" + } + ], + "next": null +} +``` + +## List all sources + +Sources are the actions that trigger the event hook. The `/sources` JSON output follows the following pattern: +- 1st level = The source, which is the action that triggers the event hook. +- 2nd level = The event, which is the Kong entity the event hook will listen to for events. +- 3rd level = The available template parameters for use in webhook-custom payloads. + +For instance, in the example below `balancer` is the source, `health` is the event, and `upstream_id`, +`ip`, `port`, `hostname`, and `health` are the available template parameters. + +**Endpoint** + +
/event-hooks/sources/
+ +**Response** + +```json +{ + "data": { + "balancer": { + "health": { + "fields": [ + "upstream_id", + "ip", + "port", + "hostname", + "health" + ] + } + }, + "crud": { + "acls": { + "fields": [ + "operation", + "entity", + "old_entity", + "schema" + ] + }, + . . . + + "rate-limiting-advanced": { + "rate-limit-exceeded": { + "description": "Run an event when a rate limit has been exceeded", + "fields": [ + "consumer", + "ip", + "service", + "rate", + "limit", + "window" + ], + "unique": [ + "consumer", + "ip", + "service" + ] + } + } + } +} +``` + +{:.note} +> **Note:** The response has been shortened because it is too long to include in its entirety. +The ellipsis in the center of the response represents the missing content. + +## List all events for a source + +Events are the Kong entities the event hook will listen to for events. With this endpoint you +can list all of the events associated with a particular source. + +
/event-hooks/sources/{source}/
+ +The following response lists all of the events for the `dao:crud` source. + +**Response** + +```json +{ + "data": { + "create": { + "fields": [ + "operation", + "entity", + "old_entity", + "schema" + ] + }, + "delete": { + "fields": [ + "operation", + "entity", + "old_entity", + "schema" + ] + }, + "update": { + "fields": [ + "operation", + "entity", + "old_entity", + "schema" + ] + } + } +} +``` + +## Add a webhook + +**Endpoint** + +
/event-hooks
+ +**Request Body** + +| Attribute | Description | +| ---------: | -------- | +| `event`
*optional* | A string describing the Kong entity the event hook will listen to for events. | +| `handler`
*required* | A string describing one of four handler options: webhook, webhook-custom, log, or lambda. | +| `source`
*required* | A string describing the action that triggers the event hook. | +| `snooze`
*optional* | An optional integer describing the time in seconds to delay an event trigger to avoid spamming an integration. | +| `on_change`
*optional* | An optional boolean indicating whether to trigger an event when key parts of a payload have changed. | +| `config.url`
*required* | The URL the JSON POST request is made to with the event data as the payload. | +| `config.headers`
*optional* | An object defining additional HTTP headers to send in the webhook request, for example `{"X-Custom-Header": "My Value"}`.| +| `config.secret`
*optional* | An optional string used to sign the remote webhook for remote verification. When set, Kong will sign the body of the event hook with HMAC-SHA1 and include it in a header, `x-kong-signature`, to the remote endpoint. | +| `config.ssl_verify`
*optional* | A boolean indicating whether to verify the SSL certificate of the remote HTTPS server where the event hook will be sent. The default is `false`. | + +**Response** + +```json +{ + "config": { + "headers": {}, + "secret": null, + "ssl_verify": false, + "url": "https://webhook.site/a1b2c3-d4e5-g6h7-i8j9-k1l2m3n4o5p6" + }, + "created_at": 1627581575, + "event": "consumers", + "handler": "webhook", + "id": "c57340ab-9fed-40fd-bb7e-1cef8d37c2df", + "on_change": null, + "snooze": null, + "source": "crud" +} +``` + +## Add a custom webhook + +**Endpoint** + +
/event-hooks
+ +**Request Body** + +| Attribute | Description | +| ---------: | -------- | +| `event`
*optional* | A string describing the Kong entity the event-hook will listen to for events. | +| `handler`
*required* | A string describing one of four handler options: webhook, webhook-custom, log, or lambda. | +| `source`
*required* | A string describing the action that triggers the event hook. | +| `snooze`
*optional* | An optional integer describing the time in seconds to delay an event trigger to avoid spamming an integration. | +| `on_change`
*optional* | An optional boolean indicating whether to trigger an event when key parts of a payload have changed. | +| `config.url`
*required* | The URL the JSON POST request is made to with the event data as the payload. | +| `config.method`
*required* | The HTTP method used to create the custom webhook. | +| `config.payload`
*optional* | An object that includes key/value pairs that describe the configurable payload body. Supports templating. The full list of available template parameters can be found in the `/sources` API output, under the `fields` JSON object. | +| `config.payload_format`
*optional* | A optional boolean (defaults to `true`) indicating whether to format the `config.payload` with resty templating. When set to `false`, the payload is sent as a raw object. | +| `config.body`
*optional* | An optional string sent in the remote request. | +| `config.body_format`
*optional* | An optional boolean (defaults to `true`) indicating whether to format the `config.body` with resty templating. When set to `false`, the body is sent as a raw object. To see all the available parameters defined for a specific `source`, check the source fields displayed by the `/event-hooks/source` endpoint. | +| `config.headers` | An object defining additional HTTP headers to send in the webhook request, for example `{"Content-type": "application/json", "X-Custom-Header": "My Value"}`. | +| `config.headers_format`
*optional* | An optional boolean (defaults to `false`) indicating whether to format the `config.headers` with resty templating. When set to `true`, the `config.headers` value will be treated as a template. To see all the available parameters defined for a specific `source`, check the source fields displayed by the `/event-hooks/sources` endpoint. | +| `config.secret`
*optional* | An optional string used to sign the remote webhook for remote verification. When set, Kong will sign the body of the event hook with HMAC-SHA1 and include it in a header, `x-kong-signature`, to the remote endpoint. | +| `config.ssl_verify`
*optional* | A boolean indicating whether to verify the SSL certificate of the remote HTTPS server where the event hook will be sent. The default value is `false`. | + +**Response** + +```json +{ + "config": { + "body": null, + "body_format": true, + "headers": { + "content-type": "application/json" + }, + "headers_format": false, + "method": "POST", + "payload": { + "text": "Admin account `{{ entity.username }}` {{ operation }}d; email address set to `{{ entity.email }}`" + }, + "payload_format": true, + "secret": null, + "ssl_verify": false, + "url": "https://hooks.slack.com/services/foo/bar/baz" + }, + "created_at": 1627588552, + "event": "admins", + "handler": "webhook-custom", + "id": "937df175-3db2-4e6d-8aa1-d95c94a76089", + "on_change": null, + "snooze": null, + "source": "crud" +} +``` + +## Add a log event hook + +**Endpoint** + +
/event-hooks
+ +**Request Body** + +| Attribute | Description | +| ---------: | -------- | +| `event`
*optional* | A string describing the Kong entity the event hook will listen to for events. | +| `handler`
*required* | A string describing one of four handler options: webhook, webhook-custom, log, or lambda. | +| `source`
*required* | A string describing the action that triggers the event hook. | +| `snooze`
*optional* | An optional integer describing the time in seconds to delay an event trigger to avoid spamming an integration. | +| `on_change`
*optional* | An optional boolean indicating whether to trigger an event when key parts of a payload have changed. | + +**Response** + +```json +{ + "config": {}, + "on_change": null, + "created_at": 1627346155, + "snooze": null, + "id": "13a16f91-68b6-4384-97f7-d02763a551ac", + "handler": "log", + "source": "crud", + "event": "routes" +} +``` + +## Add a lambda event hook + +**Endpoint** + +
/event-hooks
+ +**Request Body** + +| Attribute | Description | +| ---------: | -------- | +| `event`
*optional* | A string describing the Kong entity the event hook will listen to for events. | +| `handler`
*required* | A string describing one of four handler options: webhook, webhook-custom, log, or lambda. | +| `source`
*required* | A string describing the action that triggers the event hook. | +| `snooze`
*optional* | An optional integer describing the time in seconds to delay an event trigger to avoid spamming an integration. | +| `on_change`
*optional* | An optional boolean indicating whether to trigger an event when key parts of a payload have changed. | +| `config.functions`
*required* | An array of Lua code functions to execute on the event hook. | + +**Response** + +```json +{ + "config": { + "functions": [ + "return function (data, event, source, pid)\n local user = data.entity.username\n error(\"Event hook on consumer \" .. user .. \"\")\nend\n" + ] + }, + "created_at": 1627595513, + "event": "consumers", + "handler": "lambda", + "id": "c9fdd58d-5416-4d3a-9467-51e5cfe4ca0e", + "on_change": null, + "snooze": null, + "source": "crud" +} +``` + +## Test an event hook + +It's useful to manually trigger an event hook without provoking the event to be triggered. +For instance, you might want to test the integration, or see if your hook's service is receiving a payload from Kong. + +POST any data to `/event-hooks/:id-of-hook/test`, and the `/test` endpoint executes the with the provided data as the event payload. + +**Endpoint** + +
/event-hooks/{event-hook-id}/test
+ +**Response** + +```json +{ + "data": { + "consumer": { + "username": "Jane Austen" + }, + "event": "consumers", + "source": "crud" + }, + "result": { + "body": "", + "headers": { + "Cache-Control": "no-cache, private", + "Content-Type": "text/plain; charset=UTF-8", + "Date": "Fri, 30 Jul 2021 16:07:09 GMT", + "Server": "nginx/1.14.2", + "Transfer-Encoding": "chunked", + "Vary": "Accept-Encoding", + "X-Request-Id": "f1e703a5-d22c-435c-8d5d-bc9c561ead4a", + "X-Token-Id": "1cc1c53b-f613-467f-a5c9-20d276405104" + }, + "status": 200 + } +} + +``` + +## Ping a webhook event hook + +**Endpoint** + +
/event-hooks/{event-hook-id}/ping
+ +**Response** + +```json +{ + "source": "kong:event_hooks", + "event_hooks": { + "source": "crud", + "id": "c57340ab-9fed-40fd-bb7e-1cef8d37c2df", + "on_change": null, + "event": "consumers", + "handler": "webhook", + "created_at": 1627581575, + "config": { + "headers": { + "content-type": "application/json" + }, + "ssl_verify": false, + "url": "https://webhook.site/a1b2c3-d4e5-g6h7-i8j9-k1l2m3n4o5p6", + "secret": null + }, + "snooze": null + }, + "event": "ping" +} +``` diff --git a/app/gateway/2.6.x/admin-api/index.md b/app/gateway/2.6.x/admin-api/index.md new file mode 100644 index 000000000000..b1f83ca0aeb7 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/index.md @@ -0,0 +1,4109 @@ +--- +title: Admin API +toc: false + +service_body: | + Attributes | Description + ---:| --- + `name`
*optional* | The Service name. + `retries`
*optional* | The number of retries to execute upon failure to proxy. Default: `5`. + `protocol` | The protocol used to communicate with the upstream. Accepted values are: `"grpc"`, `"grpcs"`, `"http"`, `"https"`, `"tcp"`, `"tls"`, `"udp"`. Default: `"http"`. + `host` | The host of the upstream server. Note that the host value is case sensitive. + `port` | The upstream server port. Default: `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. Default: `60000`. + `write_timeout`
*optional* | The timeout in milliseconds between two successive write operations for transmitting a request to the upstream server. Default: `60000`. + `read_timeout`
*optional* | The timeout in milliseconds between two successive read operations for transmitting a request to the upstream server. Default: `60000`. + `tags`
*optional* | An optional set of strings associated with the Service for grouping and filtering. + `client_certificate`
*optional* | Certificate to be used as client certificate while TLS handshaking to the upstream server. With form-encoded, the notation is `client_certificate.id=`. With JSON, use "`"client_certificate":{"id":""}`. + `tls_verify`
*optional* | Whether to enable verification of upstream server TLS certificate. If set to `null`, then the Nginx default is respected. + `tls_verify_depth`
*optional* | Maximum depth of chain while verifying Upstream server's TLS certificate. If set to `null`, then the Nginx default is respected. Default: `null`. + `ca_certificates`
*optional* | Array of `CA Certificate` object UUIDs that are used to build the trust store while verifying upstream server's TLS certificate. If set to `null` when Nginx default is respected. If default CA list in Nginx are not specified and TLS verification is enabled, then handshake with upstream server will always fail (because no CA are trusted). With form-encoded, the notation is `ca_certificates[]=4e3ad2e4-0bc4-4638-8e34-c84a417ba39b&ca_certificates[]=51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515`. With JSON, use an Array. + `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"], + "client_certificate": {"id":"4e3ad2e4-0bc4-4638-8e34-c84a417ba39b"}, + "tls_verify": true, + "tls_verify_depth": null, + "ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"] + } + +service_data: | + "data": [{ + "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": "/some_api", + "connect_timeout": 60000, + "write_timeout": 60000, + "read_timeout": 60000, + "tags": ["user-level", "low-priority"], + "client_certificate": {"id":"51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"}, + "tls_verify": true, + "tls_verify_depth": null, + "ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"] + }, { + "id": "fc73f2af-890d-4f9b-8363-af8945001f7f", + "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"], + "client_certificate": {"id":"4506673d-c825-444c-a25b-602e3c2ec16e"}, + "tls_verify": true, + "tls_verify_depth": null, + "ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"] + }], + +route_body: | + Attributes | Description + ---:| --- + `name`
*optional* | The name of the Route. Name values must be unique. + `protocols` | An array of the protocols this Route should allow. See the [Route Object](#route-object) section for a list of accepted protocols. When set to only `"https"`, HTTP requests are answered with an upgrade error. When set to only `"http"`, HTTPS requests are answered with an error. Default: `["http", "https"]`. + `methods`
*semi-optional* | A list of HTTP methods that match this Route. + `hosts`
*semi-optional* | A list of domain names that match this Route. Note that the hosts value is case sensitive. 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. With form-encoded, the notation is `paths[]=/foo&paths[]=/bar`. With JSON, use an Array. + `headers`
*semi-optional* | One or more lists of values indexed by header name that will cause this Route to match if present in the request. The `Host` header cannot be used with this attribute: hosts should be specified using the `hosts` attribute. + `https_redirect_status_code` | The status code Kong responds with when all properties of a Route match except the protocol i.e. if the protocol of the request is `HTTP` instead of `HTTPS`. `Location` header is injected by Kong if the field is set to 301, 302, 307 or 308. Accepted values are: `426`, `301`, `302`, `307`, `308`. Default: `426`. + `regex_priority`
*optional* | A number used to choose which route resolves a given request when several routes match it using regexes simultaneously. When two routes match the path and have the same `regex_priority`, the older one (lowest `created_at`) is used. Note that the priority for non-regex routes is different (longer non-regex routes are matched before shorter ones). Default: `0`. + `strip_path` | When matching a Route via one of the `paths`, strip the matching prefix from the upstream request URL. Default: `true`. + `path_handling`
*optional* | Controls how the Service path, Route path and requested path are combined when sending a request to the upstream. See above for a detailed description of each behavior. Accepted values are: `"v0"`, `"v1"`. Default: `"v0"`. + `preserve_host` | 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`. + `request_buffering` | Whether to enable request body buffering or not. With HTTP 1.1, it may make sense to turn this off on services that receive data with chunked transfer encoding. Default: `true`. + `response_buffering` | Whether to enable response body buffering or not. With HTTP 1.1, it may make sense to turn this off on services that send data with chunked transfer encoding. Default: `true`. + `snis`
*semi-optional* | A list of SNIs that match this Route when using stream routing. + `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". + `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". + `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=` or `service.name=`. With JSON, use "`"service":{"id":""}` or `"service":{"name":""}`. + +route_json: | + { + "id": "d35165e2-d03e-461a-bdeb-dad0a112abfe", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-route", + "protocols": ["http", "https"], + "methods": ["GET", "POST"], + "hosts": ["example.com", "foo.test"], + "paths": ["/foo", "/bar"], + "headers": {"x-my-header":["foo", "bar"], "x-another-header":["bla"]}, + "https_redirect_status_code": 426, + "regex_priority": 0, + "strip_path": true, + "path_handling": "v0", + "preserve_host": false, + "request_buffering": true, + "response_buffering": true, + "tags": ["user-level", "low-priority"], + "service": {"id":"af8330d3-dbdc-48bd-b1be-55b98608834b"} + } + +route_data: | + "data": [{ + "id": "a9daa3ba-8186-4a0d-96e8-00d80ce7240b", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-route", + "protocols": ["http", "https"], + "methods": ["GET", "POST"], + "hosts": ["example.com", "foo.test"], + "paths": ["/foo", "/bar"], + "headers": {"x-my-header":["foo", "bar"], "x-another-header":["bla"]}, + "https_redirect_status_code": 426, + "regex_priority": 0, + "strip_path": true, + "path_handling": "v0", + "preserve_host": false, + "request_buffering": true, + "response_buffering": true, + "tags": ["user-level", "low-priority"], + "service": {"id":"127dfc88-ed57-45bf-b77a-a9d3a152ad31"} + }, { + "id": "9aa116fd-ef4a-4efa-89bf-a0b17c4be982", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-route", + "protocols": ["tcp", "tls"], + "https_redirect_status_code": 426, + "regex_priority": 0, + "strip_path": true, + "path_handling": "v0", + "preserve_host": false, + "request_buffering": true, + "response_buffering": true, + "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":"ba641b07-e74a-430a-ab46-94b61e5ea66b"} + }], + +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": "ec1a1f6f-2aa4-4e58-93ff-b56368f19b27", + "created_at": 1422386534, + "username": "my-username", + "custom_id": "my-custom-id", + "tags": ["user-level", "low-priority"] + } + +consumer_data: | + "data": [{ + "id": "a4407883-c166-43fd-80ca-3ca035b0cdb7", + "created_at": 1422386534, + "username": "my-username", + "custom_id": "my-custom-id", + "tags": ["user-level", "low-priority"] + }, { + "id": "01c23299-839c-49a5-a6d5-8864c09184af", + "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. Default: `null`.With form-encoded, the notation is `route.id=` or `route.name=`. With JSON, use "`"route":{"id":""}` or `"route":{"name":""}`. + `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. Default: `null`.With form-encoded, the notation is `service.id=` or `service.name=`. With JSON, use "`"service":{"id":""}` or `"service":{"name":""}`. + `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. Default: `null`.With form-encoded, the notation is `consumer.id=` or `consumer.username=`. With JSON, use "`"consumer":{"id":""}` or `"consumer":{"username":""}`. + `config`
*optional* | The configuration properties for the Plugin which can be found on the plugins documentation page in the [Kong Hub](/hub/). + `protocols` | A list of the request protocols that will trigger this plugin. 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 only support `"tcp"` and `"tls"`. Default: `["grpc", "grpcs", "http",`` "https"]`. + `enabled` | Whether the plugin is applied. Default: `true`. + `tags`
*optional* | An optional set of strings associated with the Plugin for grouping and filtering. + +plugin_json: | + { + "id": "ce44eef5-41ed-47f6-baab-f725cecf98c7", + "name": "rate-limiting", + "created_at": 1422386534, + "route": null, + "service": null, + "consumer": null, + "config": {"hour":500, "minute":20}, + "protocols": ["http", "https"], + "enabled": true, + "tags": ["user-level", "low-priority"] + } + +plugin_data: | + "data": [{ + "id": "02621eee-8309-4bf6-b36b-a82017a5393e", + "name": "rate-limiting", + "created_at": 1422386534, + "route": null, + "service": null, + "consumer": null, + "config": {"hour":500, "minute":20}, + "protocols": ["http", "https"], + "enabled": true, + "tags": ["user-level", "low-priority"] + }, { + "id": "66c7b5c4-4aaf-4119-af1e-ee3ad75d0af4", + "name": "rate-limiting", + "created_at": 1422386534, + "route": null, + "service": null, + "consumer": null, + "config": {"hour":500, "minute":20}, + "protocols": ["tcp", "tls"], + "enabled": true, + "tags": ["admin", "high-priority", "critical"] + }], + +certificate_body: | + Attributes | Description + ---:| --- + `cert` | PEM-encoded public certificate chain of the SSL key pair. + `key` | PEM-encoded private key of the SSL key pair. + `cert_alt`
*optional* | PEM-encoded public certificate chain of the alternate SSL key pair. This should only be set if you have both RSA and ECDSA types of certificate available and would like Kong to prefer serving using ECDSA certs when client advertises support for it. + `key_alt`
*optional* | PEM-encoded private key of the alternate SSL key pair. This should only be set if you have both RSA and ECDSA types of certificate available and would like Kong to prefer serving using ECDSA certs when client advertises support for it. + `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 convenience parameter: under the hood, it creates an SNI object and associates it with this certificate. To set this attribute this certificate must have a valid private key associated with it. + `passphrase`
*optional* (Enterprise only) | To load an encrypted private key into Kong, specify the passphrase using this attribute. Kong will decrypt the private key and store it in its database. To encrypt the private key and other sensitive information in Kong's database, consider using DB encryption. + + +certificate_json: | + { + "id": "7fca84d6-7d37-4a74-a7b0-93e576089a41", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "cert_alt": "-----BEGIN CERTIFICATE-----...", + "key_alt": "-----BEGIN EC PRIVATE KEY-----...", + "tags": ["user-level", "low-priority"] + } + +certificate_data: | + "data": [{ + "id": "d044b7d4-3dc2-4bbc-8e9f-6b7a69416df6", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "cert_alt": "-----BEGIN CERTIFICATE-----...", + "key_alt": "-----BEGIN EC PRIVATE KEY-----...", + "tags": ["user-level", "low-priority"] + }, { + "id": "a9b2107f-a214-47b3-add4-46b942187924", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "cert_alt": "-----BEGIN CERTIFICATE-----...", + "key_alt": "-----BEGIN EC PRIVATE KEY-----...", + "tags": ["admin", "high-priority", "critical"] + }], + +ca_certificate_body: | + Attributes | Description + ---:| --- + `cert` | PEM-encoded public certificate of the CA. + `cert_digest`
*optional* | SHA256 hex digest of the public certificate. + `tags`
*optional* | An optional set of strings associated with the Certificate for grouping and filtering. + +ca_certificate_json: | + { + "id": "04fbeacf-a9f1-4a5d-ae4a-b0407445db3f", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "cert_digest": "c641e28d77e93544f2fa87b2cf3f3d51...", + "tags": ["user-level", "low-priority"] + } + +ca_certificate_data: | + "data": [{ + "id": "43429efd-b3a5-4048-94cb-5cc4029909bb", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "cert_digest": "c641e28d77e93544f2fa87b2cf3f3d51...", + "tags": ["user-level", "low-priority"] + }, { + "id": "d26761d5-83a4-4f24-ac6c-cff276f2b79c", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "cert_digest": "c641e28d77e93544f2fa87b2cf3f3d51...", + "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. The Certificate must have a valid private key associated with it to be used by the SNI object. With form-encoded, the notation is `certificate.id=`. With JSON, use "`"certificate":{"id":""}`. + +sni_json: | + { + "id": "91020192-062d-416f-a275-9addeeaffaf2", + "name": "my-sni", + "created_at": 1422386534, + "tags": ["user-level", "low-priority"], + "certificate": {"id":"a2e013e8-7623-4494-a347-6d29108ff68b"} + } + +sni_data: | + "data": [{ + "id": "147f5ef0-1ed6-4711-b77f-489262f8bff7", + "name": "my-sni", + "created_at": 1422386534, + "tags": ["user-level", "low-priority"], + "certificate": {"id":"a3ad71a8-6685-4b03-a101-980a953544f6"} + }, { + "id": "b87eb55d-69a1-41d2-8653-8d706eecefc0", + "name": "my-sni", + "created_at": 1422386534, + "tags": ["admin", "high-priority", "critical"], + "certificate": {"id":"4e8d95d4-40f2-4818-adcb-30e00c349618"} + }], + +upstream_body: | + Attributes | Description + ---:| --- + `name` | This is a hostname, which must be equal to the `host` of a Service. + `algorithm`
*optional* | Which load balancing algorithm to use. Accepted values are: `"consistent-hashing"`, `"least-connections"`, `"round-robin"`. Default: `"round-robin"`. + `hash_on`
*optional* | What to use as hashing input. Using `none` results in a weighted-round-robin scheme with no hashing. Accepted values are: `"none"`, `"consumer"`, `"ip"`, `"header"`, `"cookie"`. Default: `"none"`. + `hash_fallback`
*optional* | What to use as hashing input if the primary `hash_on` does not return a hash (for example, header is missing, or no Consumer identified). Not available if `hash_on` is set to `cookie`. Accepted values are: `"none"`, `"consumer"`, `"ip"`, `"header"`, `"cookie"`. Default: `"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`. Default: `"/"`. + `slots`
*optional* | The number of slots in the load balancer algorithm. If `algorithm` is set to `round-robin`, this setting determines the maximum number of slots. If `algorithm` is set to `consistent-hashing`, this setting determines the actual number of slots in the algorithm. Accepts an integer in the range `10`-`65536`. Default: `10000`. + `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. Default: `[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. + `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. Default: `0`. + `healthchecks.passive.``type`
*optional* | Whether to perform passive health checks interpreting HTTP/HTTPS statuses, or just check for TCP connection success. In passive checks, `http` and `https` options are equivalent. Accepted values are: `"tcp"`, `"http"`, `"https"`, `"grpc"`, `"grpcs"`. Default: `"http"`. + `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. Default: `[429, 500, 503]`. With form-encoded, the notation is `http_statuses[]=429&http_statuses[]=500`. With JSON, use an Array. + `healthchecks.passive.``unhealthy.timeouts`
*optional* | Number of timeouts in proxied traffic to consider a target unhealthy, as observed by passive health checks. Default: `0`. + `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. Default: `0`. + `healthchecks.passive.``unhealthy.tcp_failures`
*optional* | Number of TCP failures in proxied traffic to consider a target unhealthy, as observed by passive health checks. Default: `0`. + `healthchecks.active.``timeout`
*optional* | Socket timeout for active health checks (in seconds). Default: `1`. + `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.``http_path`
*optional* | Path to use in GET HTTP request to run as a probe on active health checks. Default: `"/"`. + `healthchecks.active.``concurrency`
*optional* | Number of targets to check concurrently in active health checks. Default: `10`. + `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. Default: `true`. + `healthchecks.active.type`
*optional* | Whether to perform active health checks using HTTP or HTTPS, or just attempt a TCP connection. Accepted values are: `"tcp"`, `"http"`, `"https"`, `"grpc"`, `"grpcs"`. Default: `"http"`. + `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. Default: `[200, 302]`. With form-encoded, the notation is `http_statuses[]=200&http_statuses[]=302`. With JSON, use an Array. + `healthchecks.active.``healthy.successes`
*optional* | Number of successes in active probes (as defined by `healthchecks.active.healthy.http_statuses`) to consider a target healthy. Default: `0`. + `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. Default: `0`. + `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. Default: `[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.timeouts`
*optional* | Number of timeouts in active probes to consider a target unhealthy. Default: `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. Default: `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. Default: `0`. + `healthchecks.active.``unhealthy.tcp_failures`
*optional* | Number of TCP failures in active probes to consider a target unhealthy. Default: `0`. + `healthchecks.threshold`
*optional* | The minimum percentage of the upstream's targets' weight that must be available for the whole upstream to be considered healthy. Default: `0`. + `tags`
*optional* | An optional set of strings associated with the Upstream for grouping and filtering. + `host_header`
*optional* | The hostname to be used as `Host` header when proxying requests through Kong. + `client_certificate`
*optional* | If set, the certificate to be used as client certificate while TLS handshaking to the upstream server.With form-encoded, the notation is `client_certificate.id=`. With JSON, use "`"client_certificate":{"id":""}`. + +upstream_json: | + { + "id": "58c8ccbb-eafb-4566-991f-2ed4f678fa70", + "created_at": 1422386534, + "name": "my-upstream", + "algorithm": "round-robin", + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/", + "slots": 10000, + "healthchecks": { + "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 + }, + "type": "http", + "unhealthy": { + "http_statuses": [429, 500, 503], + "timeouts": 0, + "http_failures": 0, + "tcp_failures": 0 + } + }, + "active": { + "timeout": 1, + "https_sni": "example.com", + "http_path": "/", + "concurrency": 10, + "https_verify_certificate": true, + "type": "http", + "healthy": { + "http_statuses": [200, 302], + "successes": 0, + "interval": 0 + }, + "unhealthy": { + "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505], + "timeouts": 0, + "http_failures": 0, + "interval": 0, + "tcp_failures": 0 + } + }, + "threshold": 0 + }, + "tags": ["user-level", "low-priority"], + "host_header": "example.com", + "client_certificate": {"id":"ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6"} + } + +upstream_data: | + "data": [{ + "id": "4fe14415-73d5-4f00-9fbc-c72a0fccfcb2", + "created_at": 1422386534, + "name": "my-upstream", + "algorithm": "round-robin", + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/", + "slots": 10000, + "healthchecks": { + "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 + }, + "type": "http", + "unhealthy": { + "http_statuses": [429, 500, 503], + "timeouts": 0, + "http_failures": 0, + "tcp_failures": 0 + } + }, + "active": { + "timeout": 1, + "https_sni": "example.com", + "http_path": "/", + "concurrency": 10, + "https_verify_certificate": true, + "type": "http", + "healthy": { + "http_statuses": [200, 302], + "successes": 0, + "interval": 0 + }, + "unhealthy": { + "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505], + "timeouts": 0, + "http_failures": 0, + "interval": 0, + "tcp_failures": 0 + } + }, + "threshold": 0 + }, + "tags": ["user-level", "low-priority"], + "host_header": "example.com", + "client_certificate": {"id":"a3395f66-2af6-4c79-bea2-1b6933764f80"} + }, { + "id": "885a0392-ef1b-4de3-aacf-af3f1697ce2c", + "created_at": 1422386534, + "name": "my-upstream", + "algorithm": "round-robin", + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/", + "slots": 10000, + "healthchecks": { + "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 + }, + "type": "http", + "unhealthy": { + "http_statuses": [429, 500, 503], + "timeouts": 0, + "http_failures": 0, + "tcp_failures": 0 + } + }, + "active": { + "timeout": 1, + "https_sni": "example.com", + "http_path": "/", + "concurrency": 10, + "https_verify_certificate": true, + "type": "http", + "healthy": { + "http_statuses": [200, 302], + "successes": 0, + "interval": 0 + }, + "unhealthy": { + "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505], + "timeouts": 0, + "http_failures": 0, + "interval": 0, + "tcp_failures": 0 + } + }, + "threshold": 0 + }, + "tags": ["admin", "high-priority", "critical"], + "host_header": "example.com", + "client_certificate": {"id":"f5a9c0ca-bdbb-490f-8928-2ca95836239a"} + }], + +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 load balancer (`0`-`65535`). If the hostname resolves to an SRV record, the `weight` value will be overridden by the value from the DNS record. Default: `100`. + `tags`
*optional* | An optional set of strings associated with the Target for grouping and filtering. + +target_json: | + { + "id": "173a6cee-90d1-40a7-89cf-0329eca780a6", + "created_at": 1422386534, + "upstream": {"id":"bdab0e47-4e37-4f0b-8fd0-87d95cc4addc"}, + "target": "example.com:8000", + "weight": 100, + "tags": ["user-level", "low-priority"] + } + +target_data: | + "data": [{ + "id": "f00c6da4-3679-4b44-b9fb-36a19bd3ae83", + "created_at": 1422386534, + "upstream": {"id":"0c61e164-6171-4837-8836-8f5298726d53"}, + "target": "example.com:8000", + "weight": 100, + "tags": ["user-level", "low-priority"] + }, { + "id": "5027BBC1-508C-41F8-87F2-AB1801E9D5C3", + "created_at": 1422386534, + "upstream": {"id":"68FDB05B-7B08-47E9-9727-AF7F897CFF1A"}, + "target": "example.com:8000", + "weight": 100, + "tags": ["admin", "high-priority", "critical"] + }], + + +--- + +{{site.base_gateway}} 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. + +--- + + +## DB-less Mode + + +In [DB-less mode](../reference/db-less-and-declarative-config/), the 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 Kong 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. + +In DB-less mode, you configure {{site.base_gateway}} declaratively. +Therefore, the Admin API is mostly read-only. The only tasks it can perform are all +related to handling the declarative config, including: + +* [Validating configurations against schemas](#validate-a-configuration-against-a-schema) +* [Validating plugin configurations against schemas](#validate-a-plugin-configuration-against-the-schema) +* [Reloading the declarative configuration](#reload-declarative-configuration) +* [Setting a target's health status in the load balancer](#set-target-as-healthy) + + +--- + + +## Declarative Configuration + +{:.note} +> **Note:** We recommend using decK +to manage your declarative configuration. See the [decK documentation](/deck/) +for more information. + +Loading the declarative configuration of entities into {{site.base_gateway}} +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, see the +[declarative configuration](../reference/db-less-and-declarative-config/) documentation. + + +
/config
+ +{:.indent} +Attributes | Description +---:| --- +`config`
**required** | The config data (in YAML or JSON format) to be loaded. + + +#### Request Querystring Parameters + +Attributes | Description +---:| --- +`check_hash`
*optional* | If set to 1, Kong will compare the hash of the input config data against that of the previous one. If the configuration is identical, it will not reload it and will return HTTP 304. + + +#### Response + +``` +HTTP 200 OK +``` + +``` json +{ + { + "services": [], + "routes": [] + } +} +``` + +The response contains a list of all the entities that were parsed from the +input file. + +--- + + +## Supported Content Types + +The Admin API accepts the following content types on every endpoint: + +- **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" + } +} +``` + +An example adding a Route to a Service named `test-service`: + +``` +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -H "Content-Type: application/json" \ + -d '{"name": "test-route", "paths": [ "/path/one", "/path/two" ]}' +``` + +- **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 +``` + +When specifying arrays, send the values in order, or use square brackets (numbering +inside the brackets is optional but if provided it must be 1-indexed, and +consecutive). An example Route added to a Service named `test-service`: + +``` +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -d "name=test-route" \ + -d "paths[1]=/path/one" \ + -d "paths[2]=/path/two" +``` + +The following two examples are identical to the one above, but less explicit: +``` +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -d "name=test-route" \ + -d "paths[]=/path/one" \ + -d "paths[]=/path/two" + +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -d "name=test-route" \ + -d "paths=/path/one" \ + -d "paths=/path/two" +``` + + +- **multipart/form-data** + +Similar to URL-encoded, this content type uses dotted keys to reference nested +objects. Here is an example of sending a Lua file to the pre-function Kong plugin: + +``` +curl -i -X POST http://localhost:8001/services/plugin-testing/plugins \ + -F "name=pre-function" \ + -F "config.access=@custom-auth.lua" +``` + +When specifying arrays for this content-type, the array indices must be specified. +An example Route added to a Service named `test-service`: + +``` +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -F "name=test-route" \ + -F "paths[1]=/path/one" \ + -F "paths[2]=/path/two" +``` + +--- + +## Information Routes + + + +### Retrieve Node Information +{:.badge .dbless} + +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. + + +--- + +### Check Endpoint Or Entity Existence +{:.badge .dbless} + +Similar to `HTTP GET`, but does not return the body. Returns `HTTP 200` when the endpoint exits or `HTTP 404` when it does not. Other status codes are possible. + +
/<any-endpoint>
+ +#### Response + +``` +HTTP 200 OK +``` + +```http +Access-Control-Allow-Origin: * +Content-Length: 11389 +Content-Type: application/json; charset=utf-8 +X-Kong-Admin-Latency: 1 +``` + + +--- + +### List HTTP Methods by Endpoint +{:.badge .dbless} + +List all the supported `HTTP` methods by an endpoint. This can also be used with a `CORS` preflight request. + +
/<any-endpoint>
+ +#### Response + +``` +HTTP 204 No Content +``` + +```http +Access-Control-Allow-Headers: Content-Type +Access-Control-Allow-Methods: GET, HEAD, OPTIONS +Access-Control-Allow-Origin: * +Allow: GET, HEAD, OPTIONS +``` + + +--- + +### List Available Endpoints +{:.badge .dbless} + +List all available endpoints provided by the Admin API. + +
/endpoints
+ +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + "/", + "/acls", + "/acls/{acls}", + "/acls/{acls}/consumer", + "/basic-auths", + "/basic-auths/{basicauth_credentials}", + "/basic-auths/{basicauth_credentials}/consumer", + "/ca_certificates", + "/ca_certificates/{ca_certificates}", + "/cache", + "/cache/{key}", + "..." + ] +} +``` + + +--- + +### Validate A Configuration against A Schema +{:.badge .dbless} + +Check validity of a configuration against its entity schema. +This allows you to test your input before submitting a request +to the entity endpoints of the Admin API. + +Note that this only performs the schema validation checks, +checking that the input configuration is well-formed. +A requests to the entity endpoint using the given configuration +may still fail due to other reasons, such as invalid foreign +key relationships or uniqueness check failures against the +contents of the data store. + + +
/schemas/{entity}/validate
+ +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "message": "schema validation successful" +} +``` + + +--- + +### Retrieve Entity Schema +{:.badge .dbless} + +Retrieve the schema of an entity. This is useful to +understand what fields an entity accepts, and can be used for building +third-party integrations to the Kong. + + +
/schemas/{entity name}
+ +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "fields": [ + { + "id": { + "auto": true, + "type": "string", + "uuid": true + } + }, + { + "created_at": { + "auto": true, + "timestamp": true, + "type": "integer" + } + }, + ... + ] +} +``` + + +--- + +### Retrieve Plugin Schema +{:.badge .dbless} + +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. + + +
/schemas/plugins/{plugin name}
+ +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "fields": { + "hide_credentials": { + "default": false, + "type": "boolean" + }, + "key_names": { + "default": "function", + "required": true, + "type": "array" + } + } +} +``` + + +--- + +### Validate A Plugin Configuration against The Schema +{:.badge .dbless} + +Check validity of a plugin configuration against the plugins entity schema. +This allows you to test your input before submitting a request +to the entity endpoints of the Admin API. + +Note that this only performs the schema validation checks, +checking that the input configuration is well-formed. +A requests to the entity endpoint using the given configuration +may still fail due to other reasons, such as invalid foreign +key relationships or uniqueness check failures against the +contents of the data store. + + +
/schemas/plugins/validate
+ +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "message": "schema validation successful" +} +``` + + +--- + +## Health Routes + + + +### Retrieve Node Status +{:.badge .dbless} + +Retrieve usage information about a node, with some basic information +about the connections being processed by the underlying nginx process, +the status of the database connection, and node's memory usage. + +If you want to monitor the Kong process, since Kong is built on top +of nginx, every existing nginx monitoring tool or agent can be used. + + +
/status
+ +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "database": { + "reachable": true + }, + "memory": { + "workers_lua_vms": [{ + "http_allocated_gc": "0.02 MiB", + "pid": 18477 + }, { + "http_allocated_gc": "0.02 MiB", + "pid": 18478 + }], + "lua_shared_dicts": { + "kong": { + "allocated_slabs": "0.04 MiB", + "capacity": "5.00 MiB" + }, + "kong_db_cache": { + "allocated_slabs": "0.80 MiB", + "capacity": "128.00 MiB" + }, + } + }, + "server": { + "total_requests": 3, + "connections_active": 1, + "connections_accepted": 1, + "connections_handled": 1, + "connections_reading": 0, + "connections_writing": 1, + "connections_waiting": 0 + } +} +``` + +* `memory`: Metrics about the memory usage. + * `workers_lua_vms`: An array with all workers of the Kong node, where each + entry contains: + * `http_allocated_gc`: HTTP submodule's Lua virtual machine's memory + usage information, as reported by `collectgarbage("count")`, for every + active worker, i.e. a worker that received a proxy call in the last 10 + seconds. + * `pid`: worker's process identification number. + * `lua_shared_dicts`: An array of information about dictionaries that are + shared with all workers in a Kong node, where each array node contains how + much memory is dedicated for the specific shared dictionary (`capacity`) + and how much of said memory is in use (`allocated_slabs`). + These shared dictionaries have least recent used (LRU) eviction + capabilities, so a full dictionary, where `allocated_slabs == capacity`, + will work properly. However for some dictionaries, e.g. cache HIT/MISS + shared dictionaries, increasing their size can be beneficial for the + overall performance of a Kong node. + * The memory usage unit and precision can be changed using the querystring + arguments `unit` and `scale`: + * `unit`: one of `b/B`, `k/K`, `m/M`, `g/G`, which will return results + in bytes, kibibytes, mebibytes, or gibibytes, respectively. When + "bytes" are requested, the memory values in the response will have a + number type instead of string. Defaults to `m`. + * `scale`: the number of digits to the right of the decimal points when + values are given in human-readable memory strings (unit other than + "bytes"). Defaults to `2`. + You can get the shared dictionaries memory usage in kibibytes with 4 + digits of precision by doing: `GET /status?unit=k&scale=4` +* `server`: Metrics about the nginx HTTP/S server. + * `total_requests`: The total number of client requests. + * `connections_active`: The current number of active client + connections including Waiting connections. + * `connections_accepted`: The total number of accepted client + connections. + * `connections_handled`: The total number of handled connections. + Generally, the parameter value is the same as accepts unless + some resource limits have been reached. + * `connections_reading`: The current number of connections + where Kong is reading the request header. + * `connections_writing`: The current number of connections + where nginx is writing the response back to the client. + * `connections_waiting`: The current number of idle client + connections waiting for a request. +* `database`: Metrics about the database. + * `reachable`: A boolean value reflecting the state of the + database connection. Please note that this flag **does not** + reflect the health of the database itself. + + +--- + +## Tags + +Tags are strings associated to entities in Kong. + +Tags can contain almost all UTF-8 characters, with the following exceptions: + +- `,` and `/` are reserved for filtering tags with "and" and "or", so they are not allowed in tags. +- Non-printable ASCII (for example, the space character) is not allowed. + +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 +{:.badge .dbless} + +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 +{:.badge .dbless} + +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Service + +
/services
+ + +##### Create Service Associated to a Specific Certificate + +
/certificates/{certificate name or id}/services
+ +{:.indent} +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 Service. + + +#### Request Body + +{{ page.service_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.service_json }} +``` + + +--- + +### List Services +{:.badge .dbless} + +##### List All Services + +
/services
+ + +##### List Services Associated to a Specific Certificate + +
/certificates/{certificate name or id}/services
+ +{:.indent} +Attributes | Description +---:| --- +`certificate name or id`
**required** | The unique identifier or the `name` attribute of the Certificate whose Services are to be retrieved. When using this endpoint, only Services associated to the specified Certificate will be listed. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.service_data }} + "next": "http://localhost:8001/services?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Service +{:.badge .dbless} + +##### Retrieve Service + +
/services/{service name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to retrieve. + + +##### Retrieve Service Associated to a Specific Certificate + +
/certificates/{certificate id}/services/{service name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to retrieve. +`service 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
+ +{:.indent} +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
+ +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Service + +
/services/{service name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to update. + + +##### Update Service Associated to a Specific Certificate + +
/certificates/{certificate id}/services/{service name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to update. +`service 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
+ +{:.indent} +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
+ +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Service + +
/services/{service name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`service 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 Certificate + +
/certificates/{certificate id}/services/{service name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to create or update. +`service 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
+ +{:.indent} +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
+ +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Service + +
/services/{service name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to delete. + + +##### Delete Service Associated to a Specific Certificate + +
/certificates/{certificate id}/services/{service name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to delete. +`service name or id`
**required** | The unique identifier **or** the name of the Service to delete. + +#### 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. + +You need at least one matching rule that applies to the protocol being matched +by the Route. Depending on the protocols configured to be matched by the Route +(as defined with the `protocols` field), this means that at least one of the +following attributes must be set: + +* For `http`, at least one of `methods`, `hosts`, `headers` or `paths`; +* For `https`, at least one of `methods`, `hosts`, `headers`, `paths` or `snis`; +* For `tcp`, at least one of `sources` or `destinations`; +* For `tls`, at least one of `sources`, `destinations` or `snis`; +* For `grpc`, at least one of `hosts`, `headers` or `paths`; +* For `grpcs`, at least one of `hosts`, `headers`, `paths` or `snis`. + +#### Path handling algorithms + +`"v0"` is the behavior used in Kong 0.x and 2.x. It treats `service.path`, `route.path` and request path as +*segments* of a URL. It will always join them via slashes. Given a service path `/s`, route path `/r` +and request path `/re`, the concatenated path will be `/s/re`. If the resulting path is a single slash, +no further transformation is done to it. If it's longer, then the trailing slash is removed. + +`"v1"` is the behavior used in Kong 1.x. It treats `service.path` as a *prefix*, and ignores the initial +slashes of the request and route paths. Given service path `/s`, route path `/r` and request path `/re`, +the concatenated path will be `/sre`. + +Both versions of the algorithm detect "double slashes" when combining paths, replacing them by single +slashes. + +The following table shows the possible combinations of path handling version, strip path, and request: + +| `service.path` | `route.path` | `request` |`route.strip_path` | `route.path_handling` | request path | upstream path | +|----------------|--------------|-----------|-------------------|-----------------------|--------------|---------------| +| `/s` | `/fv0` | `req` | `false` | `v0` | `/fv0/req` | `/s/fv0/req` | +| `/s` | `/fv0` | `blank` | `false` | `v0` | `/fv0` | `/s/fv0` | +| `/s` | `/fv1` | `req` | `false` | `v1` | `/fv1/req` | `/sfv1/req` | +| `/s` | `/fv1` | `blank` | `false` | `v1` | `/fv1` | `/sfv1` | +| `/s` | `/tv0` | `req` | `true` | `v0` | `/tv0/req` | `/s/req` | +| `/s` | `/tv0` | `blank` | `true` | `v0` | `/tv0` | `/s` | +| `/s` | `/tv1` | `req` | `true` | `v1` | `/tv1/req` | `/s/req` | +| `/s` | `/tv1` | `blank` | `true` | `v1` | `/tv1` | `/s` | +| `/s` | `/fv0/` | `req` | `false` | `v0` | `/fv0/req` | `/s/fv0/req` | +| `/s` | `/fv0/` | `blank` | `false` | `v0` | `/fv0/` | `/s/fv01/` | +| `/s` | `/fv1/` | `req` | `false` | `v1` | `/fv1/req` | `/sfv1/req` | +| `/s` | `/fv1/` | `blank` | `false` | `v1` | `/fv1/` | `/sfv1/` | +| `/s` | `/tv0/` | `req` | `true` | `v0` | `/tv0/req` | `/s/req` | +| `/s` | `/tv0/` | `blank` | `true` | `v0` | `/tv0/` | `/s/` | +| `/s` | `/tv1/` | `req` | `true` | `v1` | `/tv1/req` | `/sreq` | +| `/s` | `/tv1/` | `blank` | `true` | `v1` | `/tv1/` | `/s` | + + +Routes can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.route_json }} +``` + +### Add Route + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Route + +
/routes
+ + +##### Create Route Associated to a Specific Service + +
/services/{service name or id}/routes
+ +{:.indent} +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 +{:.badge .dbless} + +##### List All Routes + +
/routes
+ + +##### List Routes Associated to a Specific Service + +
/services/{service name or id}/routes
+ +{:.indent} +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 +{:.badge .dbless} + +##### Retrieve Route + +
/routes/{route name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route to retrieve. + + +##### Retrieve Route Associated to a Specific Service + +
/services/{service name or id}/routes/{route name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to retrieve. +`route 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
+ +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Route + +
/routes/{route name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route to update. + + +##### Update Route Associated to a Specific Service + +
/services/{service name or id}/routes/{route name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to update. +`route 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
+ +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Route + +
/routes/{route name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`route 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 Service + +
/services/{service name or id}/routes/{route name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to create or update. +`route 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
+ +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Route + +
/routes/{route name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route to delete. + + +##### Delete Route Associated to a Specific Service + +
/services/{service name or id}/routes/{route name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to delete. +`route 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Consumer + +
/consumers
+ + +#### Request Body + +{{ page.consumer_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.consumer_json }} +``` + + +--- + +### List Consumers +{:.badge .dbless} + +##### 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 +{:.badge .dbless} + +##### Retrieve Consumer + +
/consumers/{consumer username or id}
+ +{:.indent} +Attributes | Description +---:| --- +`consumer 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
+ +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Consumer + +
/consumers/{consumer username or id}
+ +{:.indent} +Attributes | Description +---:| --- +`consumer 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
+ +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Consumer + +
/consumers/{consumer username or id}
+ +{:.indent} +Attributes | Description +---:| --- +`consumer 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
+ +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Consumer + +
/consumers/{consumer username or id}
+ +{:.indent} +Attributes | Description +---:| --- +`consumer 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](/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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Plugin + +
/plugins
+ + +##### Create Plugin Associated to a Specific Route + +
/routes/{route name or id}/plugins
+ +{:.indent} +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier or the `name` attribute of the Route that should be associated to the newly-created Plugin. + + +##### Create Plugin Associated to a Specific Service + +
/services/{service name or id}/plugins
+ +{:.indent} +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 Plugin. + + +##### Create Plugin Associated to a Specific Consumer + +
/consumers/{consumer name or id}/plugins
+ +{:.indent} +Attributes | Description +---:| --- +`consumer name or id`
**required** | The unique identifier or the `name` attribute 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 +{:.badge .dbless} + +##### List All Plugins + +
/plugins
+ + +##### List Plugins Associated to a Specific Route + +
/routes/{route name or id}/plugins
+ +{:.indent} +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier or the `name` attribute 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 name or id}/plugins
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier or the `name` attribute 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 name or id}/plugins
+ +{:.indent} +Attributes | Description +---:| --- +`consumer name or id`
**required** | The unique identifier or the `name` attribute 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 +{:.badge .dbless} + +##### Retrieve Plugin + +
/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin to retrieve. + + +##### Retrieve Plugin Associated to a Specific Route + +
/routes/{route name or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route to retrieve. +`plugin id`
**required** | The unique identifier of the Plugin to retrieve. + + +##### Retrieve Plugin Associated to a Specific Service + +
/services/{service name or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to retrieve. +`plugin id`
**required** | The unique identifier of the Plugin to retrieve. + + +##### Retrieve Plugin Associated to a Specific Consumer + +
/consumers/{consumer username or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`consumer username or id`
**required** | The unique identifier **or** the username of the Consumer to retrieve. +`plugin id`
**required** | The unique identifier of the Plugin to retrieve. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.plugin_json }} +``` + + +--- + +### Update Plugin + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Plugin + +
/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin to update. + + +##### Update Plugin Associated to a Specific Route + +
/routes/{route name or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route to update. +`plugin id`
**required** | The unique identifier of the Plugin to update. + + +##### Update Plugin Associated to a Specific Service + +
/services/{service name or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to update. +`plugin id`
**required** | The unique identifier of the Plugin to update. + + +##### Update Plugin Associated to a Specific Consumer + +
/consumers/{consumer username or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`consumer username or id`
**required** | The unique identifier **or** the username of the Consumer to update. +`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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Plugin + +
/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin to create or update. + + +##### Create Or Update Plugin Associated to a Specific Route + +
/routes/{route name or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route to create or update. +`plugin id`
**required** | The unique identifier of the Plugin to create or update. + + +##### Create Or Update Plugin Associated to a Specific Service + +
/services/{service name or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to create or update. +`plugin id`
**required** | The unique identifier of the Plugin to create or update. + + +##### Create Or Update Plugin Associated to a Specific Consumer + +
/consumers/{consumer username or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`consumer username or id`
**required** | The unique identifier **or** the username of the Consumer to create or update. +`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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Plugin + +
/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`plugin id`
**required** | The unique identifier of the Plugin to delete. + + +##### Delete Plugin Associated to a Specific Route + +
/routes/{route name or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`route name or id`
**required** | The unique identifier **or** the name of the Route to delete. +`plugin id`
**required** | The unique identifier of the Plugin to delete. + + +##### Delete Plugin Associated to a Specific Service + +
/services/{service name or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`service name or id`
**required** | The unique identifier **or** the name of the Service to delete. +`plugin id`
**required** | The unique identifier of the Plugin to delete. + + +##### Delete Plugin Associated to a Specific Consumer + +
/consumers/{consumer username or id}/plugins/{plugin id}
+ +{:.indent} +Attributes | Description +---:| --- +`consumer username or id`
**required** | The unique identifier **or** the username of the Consumer to delete. +`plugin id`
**required** | The unique identifier of the Plugin to delete. + + +#### Response + +``` +HTTP 204 No Content +``` + + +--- + +### Retrieve Enabled Plugins +{:.badge .dbless} + +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" + ] +} +``` + + +--- + +## Certificate Object + +A certificate object represents a public certificate, and can be optionally paired with the +corresponding private key. These objects are used by Kong to handle SSL/TLS termination for +encrypted requests, or for use as a trusted CA store when validating peer certificate of +client/service. Certificates are optionally associated with SNI objects to +tie a cert/key pair to one or more hostnames. + +If intermediate certificates are required in addition to the main +certificate, they should be concatenated together into one string according to +the following order: main certificate on the top, followed by any intermediates. + +Certificates can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.certificate_json }} +``` + +### Add Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Certificate + +
/certificates
+ + +#### Request Body + +{{ page.certificate_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.certificate_json }} +``` + + +--- + +### List Certificates +{:.badge .dbless} + +##### 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 +{:.badge .dbless} + +##### Retrieve Certificate + +
/certificates/{certificate id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to retrieve. + + +##### Retrieve Certificate Associated to a Specific Upstream + +
/upstreams/{upstream name or id}/client_certificate
+ +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream associated to the Certificate to be retrieved. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.certificate_json }} +``` + + +--- + +### Update Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Certificate + +
/certificates/{certificate id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to update. + + +##### Update Certificate Associated to a Specific Upstream + +
/upstreams/{upstream name or id}/client_certificate
+ +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream associated to the Certificate to be updated. + + +#### Request Body + +{{ page.certificate_body }} + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.certificate_json }} +``` + + +--- + +### Update Or Create Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Certificate + +
/certificates/{certificate id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to create or update. + + +##### Create Or Update Certificate Associated to a Specific Upstream + +
/upstreams/{upstream name or id}/client_certificate
+ +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream associated to the Certificate to be created or updated. + + +#### 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Certificate + +
/certificates/{certificate id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to delete. + + +##### Delete Certificate Associated to a Specific Upstream + +
/upstreams/{upstream name or id}/client_certificate
+ +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream associated to the Certificate to be deleted. + + +#### Response + +``` +HTTP 204 No Content +``` + + +--- + +## CA Certificate Object + +A CA certificate object represents a trusted CA. These objects are used by Kong to +verify the validity of a client or server certificate. + +CA Certificates can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.ca_certificate_json }} +``` + +### Add CA Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create CA Certificate + +
/ca_certificates
+ + +#### Request Body + +{{ page.ca_certificate_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.ca_certificate_json }} +``` + + +--- + +### List CA Certificates +{:.badge .dbless} + +##### List All CA Certificates + +
/ca_certificates
+ + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.ca_certificate_data }} + "next": "http://localhost:8001/ca_certificates?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve CA Certificate +{:.badge .dbless} + +##### Retrieve CA Certificate + +
/ca_certificates/{ca_certificate id}
+ +{:.indent} +Attributes | Description +---:| --- +`ca_certificate id`
**required** | The unique identifier of the CA Certificate to retrieve. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.ca_certificate_json }} +``` + + +--- + +### Update CA Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update CA Certificate + +
/ca_certificates/{ca_certificate id}
+ +{:.indent} +Attributes | Description +---:| --- +`ca_certificate id`
**required** | The unique identifier of the CA Certificate to update. + + +#### Request Body + +{{ page.ca_certificate_body }} + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.ca_certificate_json }} +``` + + +--- + +### Update Or Create CA Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update CA Certificate + +
/ca_certificates/{ca_certificate id}
+ +{:.indent} +Attributes | Description +---:| --- +`ca_certificate id`
**required** | The unique identifier of the CA Certificate to create or update. + + +#### Request Body + +{{ page.ca_certificate_body }} + + +Inserts (or replaces) the CA Certificate under the requested resource with the +definition specified in the body. The CA Certificate will be identified via the `name +or id` attribute. + +When the `name or id` attribute has the structure of a UUID, the CA Certificate being +inserted/replaced will be identified by its `id`. Otherwise it will be +identified by its `name`. + +When creating a new CA 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 CA Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete CA Certificate + +
/ca_certificates/{ca_certificate id}
+ +{:.indent} +Attributes | Description +---:| --- +`ca_certificate id`
**required** | The unique identifier of the CA 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create SNI + +
/snis
+ + +##### Create SNI Associated to a Specific Certificate + +
/certificates/{certificate name or id}/snis
+ +{:.indent} +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 +{:.badge .dbless} + +##### List All SNIs + +
/snis
+ + +##### List SNIs Associated to a Specific Certificate + +
/certificates/{certificate name or id}/snis
+ +{:.indent} +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 +{:.badge .dbless} + +##### Retrieve SNI + +
/snis/{sni name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`sni name or id`
**required** | The unique identifier **or** the name of the SNI to retrieve. + + +##### Retrieve SNI Associated to a Specific Certificate + +
/certificates/{certificate id}/snis/{sni name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to retrieve. +`sni 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update SNI + +
/snis/{sni name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`sni name or id`
**required** | The unique identifier **or** the name of the SNI to update. + + +##### Update SNI Associated to a Specific Certificate + +
/certificates/{certificate id}/snis/{sni name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to update. +`sni 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update SNI + +
/snis/{sni name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`sni name or id`
**required** | The unique identifier **or** the name of the SNI to create or update. + + +##### Create Or Update SNI Associated to a Specific Certificate + +
/certificates/{certificate id}/snis/{sni name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to create or update. +`sni 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete SNI + +
/snis/{sni name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`sni name or id`
**required** | The unique identifier **or** the name of the SNI to delete. + + +##### Delete SNI Associated to a Specific Certificate + +
/certificates/{certificate id}/snis/{sni name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to delete. +`sni 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 load balance +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Upstream + +
/upstreams
+ + +##### Create Upstream Associated to a Specific Certificate + +
/certificates/{certificate name or id}/upstreams
+ +{:.indent} +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 Upstream. + + +#### Request Body + +{{ page.upstream_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.upstream_json }} +``` + + +--- + +### List Upstreams +{:.badge .dbless} + +##### List All Upstreams + +
/upstreams
+ + +##### List Upstreams Associated to a Specific Certificate + +
/certificates/{certificate name or id}/upstreams
+ +{:.indent} +Attributes | Description +---:| --- +`certificate name or id`
**required** | The unique identifier or the `name` attribute of the Certificate whose Upstreams are to be retrieved. When using this endpoint, only Upstreams associated to the specified Certificate will be listed. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.upstream_data }} + "next": "http://localhost:8001/upstreams?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Upstream +{:.badge .dbless} + +##### Retrieve Upstream + +
/upstreams/{upstream name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream to retrieve. + + +##### Retrieve Upstream Associated to a Specific Certificate + +
/certificates/{certificate id}/upstreams/{upstream name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to retrieve. +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream to retrieve. + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.upstream_json }} +``` + +--- + +### Update Upstream + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +#### Update Upstream + +
/upstreams/{upstream name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream to update. + + +#### Update Upstream Associated to a Specific Certificate + +
/certificates/{certificate id}/upstreams/{upstream name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to update. +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream to update. + +#### Request Body + +{{ page.upstream_body }} + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.upstream_json }} +``` + +--- + +### Update Or Create Upstream + +{:.note} +> **Note**: This API is not available in DB-less mode. + +
/upstreams/{upstream name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`upstream 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 Certificate + +
/certificates/{certificate id}/upstreams/{upstream name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to create or update. +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream to create or update. + +#### 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 + +{:.note} +> **Note**: This API is not available in DB-less mode. + +
/upstreams/{upstream name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream to delete. + + +#### Delete Upstream Associated to a Specific Certificate + +
/certificates/{certificate id}/upstreams/{upstream name or id}
+ +{:.indent} +Attributes | Description +---:| --- +`certificate id`
**required** | The unique identifier of the Certificate to delete. +`upstream name or id`
**required** | The unique identifier **or** the name of the Upstream to delete. + +#### Response + +``` +HTTP 204 No Content +``` + +--- + +### Show Upstream Health for Node +{:.badge .dbless} + +Displays the health status for all Targets of a given Upstream, or for +the whole 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 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 execution. +* 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. + +When the request query parameter `balancer_health` is set to `1`, the +`data` field of the response refers to the Upstream itself, and its `health` +attribute is defined by the state of all of Upstream's Targets, according +to the field `healthchecks.threshold`. + + +
/upstreams/{name or id}/health/
+ +{:.indent} +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the Upstream for which to display Target health. + + +#### Request Querystring Parameters + +Attributes | Description +---:| --- +`balancer_health`
*optional* | If set to 1, Kong will return the health status of the Upstream itself. See the `healthchecks.threshold` property. + + +#### 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 + } + ] +} +``` + +If `balancer_health=1`: +``` +HTTP 200 OK +``` + +```json +{ + "data": { + "health": "HEALTHY", + "id": "07131005-ba30-4204-a29f-0927d53257b4" + }, + "next": null, + "node_id": "cbb297c0-14a9-46bc-ad91-1d0ef9b42df9" +} +``` + + +--- + +## 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, modified, or deleted. Changes take effect on the fly. + +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 + +{:.note} +> **Note**: This API is not available in DB-less mode. + +#### Create Target Associated to a Specific Upstream + +
/upstreams/{upstream_id}/targets
+ +{:.indent} +Attributes | Description +---:| --- +`upstream_id`
**required** | The unique identifier 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 +{:.badge .dbless} + +#### List Targets Associated to a Specific Upstream + +
/upstreams/{upstream_id}/targets
+ +{:.indent} +Attributes | Description +---:| --- +`upstream_id`
**required** | The unique identifier 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" +} +``` + + +--- + +### Update Target + +{:.note} +> **Note**: This API is not available in DB-less mode. + +Update a target. + +
/upstreams/{upstream name or id}/targets/{host:port or id}
+ +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
**required** | The unique identifier **or** the name of the upstream for which to update the target. +`host:port or id`
**required** | The host:port combination element of the target to update, or the `id` of an existing target entry. + +#### Response + +``` +HTTP 201 Created +``` + +--- + +### Delete Target + +{:.note} +> **Note**: This API is not available in DB-less mode. + +Remove a target from the load balancer. + + +
/upstreams/{upstream name or id}/targets/{host:port or id}
+ +{:.indent} +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 Address As Healthy + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +Set the current health status of an individual address resolved by a target +in the load balancer to "healthy" in the entire Kong cluster. + +This endpoint can be used to manually re-enable an address resolved by 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 address 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}/{address}/healthy
+ +{:.indent} +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. +`address`
**required** | The host/port combination element of the address to set as healthy. + + +#### Response + +``` +HTTP 204 No Content +``` + + +--- + +### Set Target Address As Unhealthy + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +Set the current health status of an individual address resolved by a target +in the load balancer to "unhealthy" in the entire Kong cluster. + +This endpoint can be used to manually disable an address and have it stop +responding to requests. Upstreams only forward requests to healthy nodes, so +this call tells Kong to start skipping this address. + +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 +addresses. Note that if active health checks are enabled and the probe detects +that the address is actually healthy, it will automatically re-enable it again. +To permanently remove a target from the balancer, you should [delete a +target](#delete-target) instead. + + +
/upstreams/{upstream name or id}/targets/{target or id}/unhealthy
+ +{:.indent} +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 +``` + + +--- + +### Set Target As Healthy +{:.badge .dbless} + +Set the current health status of a target in the load balancer to "healthy" +in the entire Kong cluster. This sets the "healthy" status to all addresses +resolved by this target. + +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
+ +{:.indent} +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 +{:.badge .dbless} + +Set the current health status of a target in the load balancer to "unhealthy" +in the entire Kong cluster. This sets the "unhealthy" status to all addresses +resolved by this target. + +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. + +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 balancer, you should [delete a +target](#delete-target) instead. + + +
/upstreams/{upstream name or id}/targets/{target or id}/unhealthy
+ +{:.indent} +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 +{:.badge .dbless} + +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/
+ +{:.indent} +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]: /gateway/{{page.release}}/reference/clustering +[cli]: /gateway/{{page.release}}/reference/cli +[active]: /gateway/{{page.release}}/reference/health-checks-circuit-breakers/#active-health-checks +[healthchecks]: /gateway/{{page.release}}/reference/health-checks-circuit-breakers +[secure-admin-api]: /gateway/{{page.release}}/admin-api/secure-admin-api +[proxy-reference]: /gateway/{{page.release}}/reference/proxy diff --git a/app/gateway/2.6.x/admin-api/licenses/examples.md b/app/gateway/2.6.x/admin-api/licenses/examples.md new file mode 100644 index 000000000000..0e6da4f5d817 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/licenses/examples.md @@ -0,0 +1,142 @@ +--- +title: Licenses Examples +badge: enterprise +--- + +{:.note} +> **Note:** The `/licenses` endpoint does not override standard +license configuration. + +The `/licenses` endpoint provides a way to configure your {{site.base_gateway}} +without using environment variables or placing a plaintext file +in your system directories. In a hybrid mode deployment, the Admin API +`/licenses` endpoint also configures all data planes in the cluster, simplifying +the configuration process. + +## Prerequisites +Remove all standard license configurations from traditional deployments, control +planes, and data planes. + +If you deploy a license using environmental variables or a plaintext +file, this configuration takes precedence over the +`/licenses` endpoint and **does not** communicate any changes to the Admin API. +If you try to use the `/licenses` endpoint while having a license configured +in some other way, the new license will not apply. + +## List all licenses + +Submit the following request: + +```bash +http GET :8001/licenses +``` + +{% navtabs codeblock %} +{% navtab Response when license exists %} +```json +{ + "data": [ + { + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "updated_at": 1500508800 + }, + ], + "next": null, +} +``` +{% endnavtab %} +{% navtab Response if there is no license %} + +```json +{ + "data": [], + "next": null +} +``` +{% endnavtab %} +{% endnavtabs %} + +## List a license + +Using the ID of the license, submit the following request: + +```bash +http GET :8001/licenses/30b4edb7-0847-4f65-af90-efbed8b0161f +``` + +```json +{ + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +## Add a license + +### Auto-generated ID + +To generate an ID automatically, submit a `POST` request directly to `/licenses`: + +```bash +http POST :8001/licenses \ + payload='{"license":{"payload":{"admin_seats":"1","customer":"Example Company, Inc","dataplanes":"1","license_creation_date":"2017-07-20","license_expiration_date":"2017-07-20","license_key":"00141000017ODj3AAG_a1V41000004wT0OEAU","product_subscription":"Konnect Enterprise","support_plan":"None"},"signature":"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b","version":"1"}}' +``` + +Response: +```json +{ + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +### Manually provided ID + +To create a license with a custom ID, submit a `PUT` request to +`/licenses/`: + +```bash +http PUT :8001/licenses/e8201120-4ee3-43ca-9e92-3fed08b1a15d \ + payload='{"license":{"payload":{"admin_seats":"1","customer":"Example Company, Inc","dataplanes":"1","license_creation_date":"2017-07-20","license_expiration_date":"2017-07-20","license_key":"00141000017ODj3AAG_a1V41000004wT0OEAU","product_subscription":"Konnect Enterprise","support_plan":"None"},"signature":"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b","version":"1"}}' +``` + +Response: +```json +{ + "created_at": 1500508800, + "id": "e8201120-4ee3-43ca-9e92-3fed08b1a15d", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +**Note**: If the provided ID exists, the request will perform + an update to the license for the given ID instead of creating a new + `license` entity. + +## Update a license + +To update a license, submit a `PATCH` request to an existing license ID: + +```bash +http PATCH :8001/licenses/30b4edb7-0847-4f65-af90-efbed8b0161f \ + payload='{"license":{"payload":{"admin_seats":"1","customer":"Example Company, Inc","dataplanes":"1","license_creation_date":"2017-07-20","license_expiration_date":"2017-07-21","license_key":"00141000017ODj3AAG_a1V41000004wT0OEAU","product_subscription":"Konnect Enterprise","support_plan":"None"},"signature":"24cc21223633044c15c300be19cacc26ccc5aca0dd9a12df8a7324a1970fe304bc07b8dcd7fb08d7b92e04169313377ae3b550ead653b951bc44cd2eb59f6beb","version":"1"}}' +``` + +Response: +```json +{ + "created_at": 1500595200, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-21\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"24cc21223633044c15c300be19cacc26ccc5aca0dd9a12df8a7324a1970fe304bc07b8dcd7fb08d7b92e04169313377ae3b550ead653b951bc44cd2eb59f6beb\",\"version\":\"1\"}}", + "updated_at": 1500595200 +} +``` + +[services]: /gateway/{{page.release}}/admin-api/#service-object diff --git a/app/gateway/2.6.x/admin-api/licenses/reference.md b/app/gateway/2.6.x/admin-api/licenses/reference.md new file mode 100644 index 000000000000..ca9f38790549 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/licenses/reference.md @@ -0,0 +1,271 @@ +--- +title: Licenses Reference +badge: enterprise + +licenses_attribute_id: | + Attributes | Description + ---:| --- + `id` | The **license's** unique ID. + +licenses_body: | + Attribute | Description + ---:| --- + `payload` | The **Enterprise license** in JSON format. +--- + +The {{site.base_gateway}} Licenses feature is configurable through the +[Admin API]. This feature lets you configure a license in your +{{site.base_gateway}} cluster, in both traditional and hybrid mode deployments. +In hybrid mode deployments, the control plane sends licenses configured +through the `/licenses` endpoint to all data planes in the cluster. The data +planes use the most recent `updated_at` license. + +## List licenses +**Endpoint** + +
/licenses/
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "updated_at": 1500508800 + }, + ], + "next": null, +} +``` + +If there are no licenses stored by {{site.base_gateway}}, the data array will +be empty. + +```json +{ + "data": [], + "next": null +} +``` + +## Add license + +To create a license using an auto-generated UUID: + +**Endpoint** + +
/licenses/
+ +**Request Body** + +{{ page.licenses_body }} + +When using `POST`, if the request payload **does** +contain a valid {{site.base_gateway}} license, the license will be added. + +If the request payload **does not** contain a valid licence, a `400 BAD REQUEST` +will be returned. + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +## Update or add a license + +**Endpoint** + +
/licenses/{id}
+ +{{ page.licenses_attribute_id }} + +When using `PUT`, if the request payload +**does not** contain an entity's primary key (`id` for licenses), the +license will be added and assigned the given ID. + +If the request payload +**does** contain an entity's primary key (`id` for Licenses), the license +will be replaced with the given payload attribute. +If the ID is not a valid UUID, a `400 BAD REQUEST` will be returned. If the ID +is omitted, a `405 NOT ALLOWED` will be returned. + +**Request Body** + +{{ page.licenses_body }} + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1500508800, + "id": "e8201120-4ee3-43ca-9e92-3fed08b1a15d", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +## Update a license + +**Endpoint** + +
/licenses/{id}
+ +{{ page.licenses_attribute_id }} + +When using `PATCH`, if the request payload +**does** contain an entity's primary key (`id` for licenses), the license will +be replaced with the given payload attribute. + +If the request payload **does +not** contain an entity's primary key (`id` for licenses), a `404 NOT FOUND` +will be returned or if the request payload contains a invalid licence, a `400 +BAD REQUEST` will be returned. + +**Request Body** + +{{ page.licenses_body }} + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1500595200, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-21\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"24cc21223633044c15c300be19cacc26ccc5aca0dd9a12df8a7324a1970fe304bc07b8dcd7fb08d7b92e04169313377ae3b550ead653b951bc44cd2eb59f6beb\",\"version\":\"1\"}}", + "updated_at": 1500595200 +} +``` + +## List a license + +**Endpoint** + +
/licenses/{id}
+ +{{ page.licenses_attribute_id }} + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-21\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"24cc21223633044c15c300be19cacc26ccc5aca0dd9a12df8a7324a1970fe304bc07b8dcd7fb08d7b92e04169313377ae3b550ead653b951bc44cd2eb59f6beb\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +## Delete a license + +**Endpoint** + +
/licenses/{id}
+ +{{ page.licenses_attribute_id }} + +**Response** + +``` +HTTP 204 No Content +``` + +## Generate a report + +Generate a report on the {{site.base_gateway}} instance to gather usage data. + +
/license/report
+ +Fields available in the report: + +Field | Description +------|------------ +`counters.req_count` | Counts the number of requests made since the license creation date. +`db_version` | The type and version of the datastore {{site.base_gateway}} is using. +`kong_version` | The version of the {{site.base_gateway}} instance. +`license_key` | An encrypted identifier for the current license key. If no license is present, the field displays as `UNLICENSED`. +`rbac_users` | The number of users registered with through RBAC. +`services_count` | The number of configured services in the {{site.base_gateway}} instance. +`system_info` | Displays information about the system running {{site.base_gateway}}.

• `cores`: Number of CPU cores on the node
• `hostname`: Encrypted system hostname
• `uname`: Operating system +`workspaces_count` | The number of workspaces configured in the {{site.base_gateway}} instance. + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "counters":{ + "req_cnt":22 + }, + "db_version":"postgres 9.5.20", + "kong_version":"1.3-enterprise-edition", + "license_key":"ASDASDASDASDASDASDASDASDASD_a1VASASD", + "rbac_users":0, + "services_count": 27, + "system_info":{ + "cores":6, + "hostname":"264da9b95dfa", + "uname":"Linux x86_64" + }, + "workspaces_count":1 +} +``` + +If there are no licenses stored by {{site.base_gateway}}, the report will include +`"license_key": "UNLICENSED"`: + +``` +HTTP 200 OK +``` + +```json +{ + "counters":{ + "req_cnt":22 + }, + "db_version":"postgres 9.5.20", + "kong_version":"1.3-enterprise-edition", + "license_key":"ASDASDASDASDASDASDASDASDASD_a1VASASD", + "rbac_users":0, + "services_count": 27, + "system_info":{ + "cores":6, + "hostname":"264da9b95dfa", + "uname":"Linux x86_64" + }, + "workspaces_count":1 +} +``` + +[Admin API]: /gateway/{{page.release}}/admin-api/ diff --git a/app/gateway/2.6.x/admin-api/rbac/examples.md b/app/gateway/2.6.x/admin-api/rbac/examples.md new file mode 100644 index 000000000000..6194a41da917 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/rbac/examples.md @@ -0,0 +1,1046 @@ +--- +title: RBAC Examples +badge: enterprise +--- + +This chapter aims to provide a step-by-step tutorial on how to set up +RBAC and see it in action, with an end-to-end use case. The chosen +use case demonstrates how **RBAC with workspaces** can be coupled +to achieve a flexible organization of teams and users in complex +hierarchies. Make sure to read the [RBAC Overview][rbac-overview] page +and to glance over the [RBAC Admin API][rbac-admin] chapter, keeping it +open as a reference. + +## Use Case + +For the sake of example, let's say a given company has a {{site.base_gateway}} +cluster to be shared with 3 teams: teamA, teamB, and teamC. While the Kong +cluster are shared among these teams, they want to be able to segment +their entities in such a way that management of entities in one team doesn't +disrupt operation in some other team. As shown in the +[Workspaces Examples Page][workspaces-examples], such a use case is possible +with workspaces. On top of workspaces, though, each team wants to enforce +access control over their Workspace, which is possible with RBAC. **To sum up, +Workspaces and RBAC are complementary: Workspaces provide segmentation of +Admin API entities, while RBAC provides access control**. + +## Bootstrapping the first RBAC user—the Super Admin + +**Note:** It is possible to create the first Super Admin at the time +of migration as described in the [Getting Started Guide][getting-started-guide]. +If you chose this option, skip to [Enforcing RBAC](#enforcing-rbac). + +Before anything, we will assume the Kong Admin—or, more interestingly, +the KongOps Engineer—in charge of operating Kong, will create a Super Admin +user, before actually enforcing RBAC and restarting Kong with RBAC enabled. + +As Kong ships with a handy set of default RBAC Roles—the `super-admin`, +the `admin`, and `read-only`—the task of creating a Super Admin user is +quite easy: + +Create the RBAC user, named `super-admin`: + +``` +http :8001/rbac/users name=super-admin +{ + "user_token": "M8J5A88xKXa7FNKsMbgLMjkm6zI2anOY", + "id": "da80838d-49f8-40f6-b673-6fff3e2c305b", + "enabled": true, + "created_at": 1531009435000, + "name": "super-admin" +} +``` + +As the `super-admin` user name coincides with an existing `super-admin` +role, it gets automatically added to the `super-admin` role—which can be +confirmed with the following command: + +``` +http :8001/rbac/users/super-admin/roles +{ + "roles": [ + { + "comment": "Full access to all endpoints, across all workspaces", + "created_at": 1531009724000, + "name": "super-admin", + "id": "b924ac91-e83f-4136-a5a4-4a7ff92594a8" + } + ], + "user": { + "created_at": 1531009858000, + "id": "e6897cc0-0c34-4a9c-9f0b-cc65b4f04d68", + "name": "super-admin", + "enabled": true, + "user_token": "vajeOlkybsn0q0VD9qw9B3nHYOErgY7b8" + } +} + +``` + +## Enforcing RBAC + +As the `super-admin` user has just been created, the Kong Admin may now +restart Kong with RBAC enforced, with, e.g.: + +``` +KONG_ENFORCE_RBAC=on kong restart +``` + +**NOTE**: This is one of the possible ways of enforcing RBAC and restarting +Kong; another possibility is editing the Kong configuration file and +restarting. + +Before we move on, note that we will be using the Super Admin user, but we +could, in fact, be moving without RBAC enabled, and having our Kong Admin do +all the job of setting up the RBAC hierarchy. We want, however, to stress the +fact that RBAC is powerful enough to allow a flexible separation of tasks. To +summarize: + +- **Kong Admin**: this user has physical access to Kong infrastructure; her +task is to bootstrap the Kong cluster as well as its configuration, including +initial RBAC users; +- **RBAC Super Admin**: created by the Kong Admin, has the role of managing +RBAC users, roles, etc; this could all be done by the **Kong Admin**, but let's +give him a break. + +## Super Admin creates the teams Workspaces + +The Super Admin will now set up our 3 teams: teamA, teamB, and teamC, creating +one workspace for each, one admin for each. Enough talking. + +Creating workspaces for each team—this overlaps a bit with +[Workspaces Examples][workspaces-examples], yes, but it will make our +exploration of RBAC + Workspaces easier: + +**Team A**: + +``` +http :8001/workspaces name=teamA Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "name": "teamA", + "created_at": 1531014100000, + "id": "1412f3a6-4d9b-4b9d-964e-60d8d63a9d46" +} + +``` + +**Team B**: + +``` +http :8001/workspaces name=teamB Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "name": "teamB", + "created_at": 1531014143000, + "id": "7dee8c56-c6db-4125-b87a-b508baa33c66" +} +``` + +**Team C**: + +``` +http :8001/workspaces name=teamC Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "name": "teamC", + "created_at": 1531014171000, + "id": "542c8662-17cc-49eb-af50-6eb14f3b2e8a" +} +``` + +**NOTE**: this is the RBAC Super Admin creating workspaces—note his +token being passed in through the `Kong-Admin-Token` HTTP header. + +## Super Admin Creates one Admin for each Team + +**Team A**: + +``` +http :8001/teamA/rbac/users name=adminA Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "user_token": "qv1VLIpl8kHj7lC1QOKwRdCMXanqEDii", + "id": "4d315ff9-8c1a-4844-9ea2-21b16204a154", + "enabled": true, + "created_at": 1531015165000, + "name": "adminA" +} +``` + +**Team B**: + +``` +http :8001/teamB/rbac/users name=adminB Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "user_token": "IX5vHVgYqM40tLcctdmzRtHyfxB4ToYv", + "id": "49641fc0-8c9d-4507-bc7a-2acac8f2903a", + "enabled": true, + "created_at": 1531015221000, + "name": "adminB" +} +``` + +**Team C**: + +``` +http :8001/teamC/rbac/users name=adminC Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "user_token": "w2f7tsuUW4BerXocZIMRQHE84nK2ZAo7", + "id": "74643f69-8852-49f9-b363-21971bac4f52", + "enabled": true, + "created_at": 1531015304000, + "name": "teamC" +} +``` + +With this, all of the teams have one admin and each admin can only be seen +in his corresponding workspace. To verify: + +``` +http :8001/teamA/rbac/users Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "created_at": 1531014784000, + "id": "1faaacd1-709f-4762-8c3e-79f268ec8faf", + "name": "adminA", + "enabled": true, + "user_token": "n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG" + } + ] +} +``` + +Similarly, workspaces teamB and teamC only show their respective admins: + +``` +http :8001/teamB/rbac/users Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "created_at": 1531014805000, + "id": "3a829408-c1ee-4764-8222-2d280a5de441", + "name": "adminB", + "enabled": true, + "user_token": "C8b6kTTN10JFyU63ORjmCQwVbvK4maeq" + } + ] +} +``` + +``` +http :8001/teamC/rbac/users Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "created_at": 1531014813000, + "id": "84d43cdb-5274-4b74-ad22-615e50f005e3", + "name": "adminC", + "enabled": true, + "user_token": "zN5Nj8U1MiGR7vVQKvl8odaGBDI6mjgY" + } + ] +} +``` + +## Super Admin Creates Admin Roles for Teams + +Super Admin is now done creating RBAC Admin users for each team; his next +task is to create admin roles that will effectively grant permissions to admin +users. + +The admin role must have access to all of the Admin API, restricted to his +workspace. + +Setting up the Admin role—pay close attention to the request parameters: + +``` +http :8001/teamA/rbac/roles/ name=admin Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "created_at": 1531016728000, + "id": "d40e61ab-8dad-4ef2-a48b-d11379f7b8d1", + "name": "admin" +} +``` + +Creating role endpoint permissions: + +``` +http :8001/teamA/rbac/roles/admin/endpoints/ endpoint=* workspace=teamA actions=* Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "endpoint": "*", + "created_at": 1531017322000, + "role_id": "d40e61ab-8dad-4ef2-a48b-d11379f7b8d1", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": false, + "workspace": "teamA" + } + ] +} +``` + +Next logical step is to add the adminA user—admin of Team A—to the Admin +role in his workspace: + +``` +http :8001/teamA/rbac/users/adminA/roles/ roles=admin Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "roles": [ + { + "comment": "Default user role generated for adminA", + "created_at": 1531014784000, + "id": "e2941b41-92a4-4f49-be89-f1a452bdecd0", + "name": "adminA" + }, + { + "created_at": 1531016728000, + "id": "d40e61ab-8dad-4ef2-a48b-d11379f7b8d1", + "name": "admin" + } + ], + "user": { + "created_at": 1531014784000, + "id": "1faaacd1-709f-4762-8c3e-79f268ec8faf", + "name": "adminA", + "enabled": true, + "user_token": "n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG" + } +} +``` + +Note the admin role in the list above. + +With these steps, Team A's admin user is now able to manage his team. To +validate that, let's try to list RBAC users in Team B using Team A's admin +user token—and see that we are not allowed to do so: + +``` +http :8001/teamB/rbac/users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "message": "Invalid RBAC credentials" +} +``` + +Said admin is, however, allowed to list RBAC users in Team A's workspace: + +``` +http :8001/teamA/rbac/users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "total": 1, + "data": [ + { + "created_at": 1531014784000, + "id": "1faaacd1-709f-4762-8c3e-79f268ec8faf", + "name": "adminA", + "enabled": true, + "user_token": "n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG" + } + ] +} +``` + +If the same procedure is repeated for Team B and Team C, they will end up with +a similar set up, with an admin role and an admin user, both restricted to the +team's workspace. + +And so Super Admin ends his participation; individual team admins are now able +to set up his teams users and entities! + +## Team Admins Create Team Regular Users + +From this point on, team admins are able to drive the process; the next logical +step is for Team users to be created; such team users could be, for example, +engineers that are part of Team A (or B or C). Let's go ahead and do that, +using Admin A's user token. + +Before regular users can be created, a role needs to be available for them. +Such a role needs to have permissions to all of Admin API endpoints, except +RBAC and Workspaces—regular users will not need access to these in general +and, if they do, the Admin can grant them. + +**Creating the regular users role**: + +``` +http :8001/teamA/rbac/roles/ name=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531020346000, + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "name": "users" +} +``` + +**Creating permissions in the regular users role**: + +First, permission to all of Admin API—positive permission on \*: + +``` +http :8001/teamA/rbac/roles/users/endpoints/ endpoint=* workspace=teamA actions=* Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "endpoint": "*", + "created_at": 1531020573000, + "role_id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": false, + "workspace": "teamA" +} +``` + +Then, filter out RBAC and workspaces with negative permissions: + +``` +http :8001/teamA/rbac/roles/users/endpoints/ endpoint=/rbac/* workspace=teamA actions=* Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "endpoint": "/rbac/*", + "created_at": 1531020744000, + "role_id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": true, + "workspace": "teamA" +} +``` + +``` +http :8001/teamA/rbac/roles/users/endpoints/ endpoint=/workspaces/* workspace=teamA actions=* Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "endpoint": "/workspaces/*", + "created_at": 1531020778000, + "role_id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": true, + "workspace": "teamA" +} +``` + +**IMPORTANT**: as explained in the [Wildcards in Permissions](#wildcards-in-permissions) +section, the meaning of `*` is not the expected generic globbing one might +be used to. As such, `/rbac/*` or `/workspaces/*` do not match all of the +RBAC and Workspaces endpoints. For example, to cover all of the RBAC API, +one would have to define permissions for the following endpoints: + +- `/rbac/*` +- `/rbac/*/*` +- `/rbac/*/*/*` +- `/rbac/*/*/*/*` +- `/rbac/*/*/*/*/*` + +Team A just got 3 new members: foogineer, bargineer, and bazgineer. Admin A +will welcome them to the team by creating RBAC users for them and giving them +access to Kong! + +Create foogineer: + +``` +http :8001/teamA/rbac/users name=foogineer Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531019797000, + "id": "0b4111da-2827-4767-8651-a327f7a559e9", + "name": "foogineer", + "enabled": true, + "user_token": "dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI" +} +``` + +Add foogineer to the `users` role: + +``` +http :8001/teamA/rbac/users/foogineer/roles roles=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for foogineer", + "created_at": 1531019797000, + "id": "125c4212-b882-432d-a323-9cbe38b1d0df", + "name": "foogineer" + }, + { + "created_at": 1531020346000, + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "name": "users" + } + ], + "user": { + "created_at": 1531019797000, + "id": "0b4111da-2827-4767-8651-a327f7a559e9", + "name": "foogineer", + "enabled": true, + "user_token": "dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI" + } +} +``` + +Create bargineer: + +``` +http :8001/teamA/rbac/users name=bargineer Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531019837000, + "id": "25dfa68e-32e8-48d8-815f-6fedfd2fb4a6", + "name": "bargineer", + "enabled": true, + "user_token": "eZj3WUc46wO3zEJbLP3Y4VGvNaUgGlyv" +} +``` + +Add bargineer to the `users` role: + +``` +http :8001/teamA/rbac/users/bargineer/roles roles=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for bargineer", + "created_at": 1531019837000, + "id": "3edb00c2-9ae1-423d-ac81-bec702c29e37", + "name": "bargineer" + }, + { + "created_at": 1531020346000, + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "name": "users" + } + ], + "user": { + "created_at": 1531019837000, + "id": "25dfa68e-32e8-48d8-815f-6fedfd2fb4a6", + "name": "bargineer", + "enabled": true, + "user_token": "eZj3WUc46wO3zEJbLP3Y4VGvNaUgGlyv" + } +} +``` + +Create bazgineer: + +``` +http :8001/teamA/rbac/users name=bazgineer Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531019937000, + "id": "ea7207d7-0d69-427b-b288-ce696b7f4690", + "name": "bazgineer", + "enabled": true, + "user_token": "r8NhaT213Zm8o1woQF4ZyQyCVjFRgGp3" +} +``` + +Add bazgineer to the `users` role: + +``` +http :8001/teamA/rbac/users/bazgineer/roles roles=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for bazgineer", + "created_at": 1531019937000, + "id": "fa409bb6-c86c-45d2-8a6b-ac8e71de2cc9", + "name": "bazgineer" + }, + { + "created_at": 1531020346000, + "name": "users", + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b" + } + ], + "user": { + "created_at": 1531019937000, + "id": "ea7207d7-0d69-427b-b288-ce696b7f4690", + "name": "bazgineer", + "enabled": true, + "user_token": "r8NhaT213Zm8o1woQF4ZyQyCVjFRgGp3" + } +} +``` + +## Regular Team Users use their tokens + +foogineer, bargineer, and bazgineer all have gotten their RBAC user tokens +from their Team A admin, and are now allowed to explore Kong—within the +confines of their Team A workspace. Let's validate they can in fact do anything +they wish, except over RBAC and Workspaces. + +Try listing Workspaces: + +``` +http :8001/teamA/workspaces/ Kong-Admin-Token:dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI +{ + "message": "foogineer, you do not have permissions to read this resource" +} +``` + +Enable some plugin—e.g., key-auth: + +``` +http :8001/teamA/plugins name=key-auth Kong-Admin-Token:dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI +{ + "created_at": 1531021732000, + "config": { + "key_in_body": false, + "run_on_preflight": true, + "anonymous": "", + "hide_credentials": false, + "key_names": [ + "apikey" + ] + }, + "id": "cdc85ef0-804b-4f92-aafd-3ff58512e445", + "enabled": true, + "name": "key-auth" +} +``` + +List currently enabled plugins: + +``` +http :8001/teamA/plugins Kong-Admin-Token:dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI +{ + "total": 1, + "data": [ + { + "created_at": 1531021732000, + "config": { + "key_in_body": false, + "run_on_preflight": true, + "anonymous": "", + "hide_credentials": false, + "key_names": [ + "apikey" + ] + }, + "id": "cdc85ef0-804b-4f92-aafd-3ff58512e445", + "name": "key-auth", + "enabled": true + } + ] +} +``` + +This ends our use case tutorial; it demonstrates the power of RBAC and +workspaces with a real-world scenario. Following, we will approach **Entity-Level +RBAC**, an extension of our powerful access control to entity-level granularity. + +## Entity-Level RBAC: a Primer + +{{site.base_gateway}}'s new RBAC implementation goes one step further in permissions +granularity: in addition to "endpoint" permissions, it supports entity-level +permissions, meaning that particular entities, identified by their unique ID, +can be allowed or disallowed access in a role. + +Refreshing our minds, RBAC is [enforced](#enforcing-rbac) with the `enforce_rbac` +configuration directive—or with its `KONG_ENFORCE_RBAC` environment variable +counterpart. Such directive is an enum, with 4 possible values: + +- `on`: similarly to the previous RBAC implementation, applies Endpoint-level +access control +- `entity`: applies **only** Entity-level access control +- `both`: applies **both Endpoint and Entity level access control** +- `off`: disables RBAC enforcement + +If one sets it to either `entity` or `both`, Kong will enforce entity-level +access control. However, as with endpoint-level access control, permissions +must be bootstrapped before enforcement is enabled. + +### Creating Entity-Level Permissions + +Team A just got one new, temporary, team member: qux. Admin A, the admin of +Team A, has already created his qux RBAC user; he needs, however, to limit +access that qux has over entities in Team A workspace, giving him read access +to only a couple of entities—say, a Service and a Route. For that, he will +use Entity-Level RBAC. + +**Admin A creates a role for the temporary user qux**: + +``` +http :8001/teamA/rbac/roles name=qux-role Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "name": "qux-role", + "created_at": 1531065975000, + "id": "ffe93269-7993-4308-965e-0286d0bc87b9" +} +``` + +We will assume the following entities exist: + +A service: + +``` +http :8001/teamA/services Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "next": null, + "data": [ + { + "host": "httpbin.konghq.com", + "created_at": 1531066074, + "connect_timeout": 60000, + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43", + "protocol": "http", + "name": "service1", + "read_timeout": 60000, + "port": 80, + "path": null, + "updated_at": 1531066074, + "retries": 5, + "write_timeout": 60000 + } + ] +} +``` + +and a Route to that Service: + +``` +http :8001/teamA/routes Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "next": null, + "data": [ + { + "created_at": 1531066253, + "id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b", + "hosts": null, + "updated_at": 1531066253, + "preserve_host": false, + "regex_priority": 0, + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "paths": [ + "/anything" + ], + "methods": null, + "strip_path": false, + "protocols": [ + "http", + "https" + ] + } + ] +} +``` + +**Admin A creates entity permissions in qux-role**: + +Add service1—whose ID is 3ed24101-19a7-4a0b-a10f-2f47bcd4ff43: + +``` +http :8001/teamA/rbac/roles/qux-role/entities entity_id=3ed24101-19a7-4a0b-a10f-2f47bcd4ff43 actions=read Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531066684000, + "role_id": "ffe93269-7993-4308-965e-0286d0bc87b9", + "entity_id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43", + "negative": false, + "entity_type": "services", + "actions": [ + "read" + ] +} +``` + +Add the route—whose ID is d25afc46-dc59-48b2-b04f-d3ebe19f6d4b: + +``` +http :8001/teamA/rbac/roles/qux-role/entities entity_id=d25afc46-dc59-48b2-b04f-d3ebe19f6d4b actions=read Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531066728000, + "role_id": "ffe93269-7993-4308-965e-0286d0bc87b9", + "entity_id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b", + "negative": false, + "entity_type": "routes", + "actions": [ + "read" + ] +} +``` + +**Admin A adds qux to his role**: + +``` +http :8001/teamA/rbac/users/qux/roles roles=qux-role Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for qux", + "created_at": 1531065373000, + "name": "qux", + "id": "31614171-4174-42b4-9fae-43c9ce14830f" + }, + { + "created_at": 1531065975000, + "name": "qux-role", + "id": "ffe93269-7993-4308-965e-0286d0bc87b9" + } + ], + "user": { + "created_at": 1531065373000, + "id": "4d87bf78-5824-4756-b0d0-ceaa9bd9b2d5", + "name": "qux", + "enabled": true, + "user_token": "sUnv6uBehM91amYRNWESsgX3HzqoBnR5" + } +} +``` + +Checking permissions appear listed: + +``` +http :8001/teamA/rbac/users/qux/permissions Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "entities": { + "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b": { + "actions": [ + "read" + ], + "negative": false + }, + "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43": { + "actions": [ + "read" + ], + "negative": false + } + }, + "endpoints": {} +} +``` + +That is, 2 entities permissions and no endpoint permissions. + +Admin A is done setting up qux, and qux can now use his user token to read +his two entities over Kong's admin API. + +We will assume that Admin A [enabled entity-level enforcement](#enforcing-rbac). +Note that as qux has **no endpoint-level permissions**, if both endpoint and +entity-level enforcement is enabled, he will not be able to read his entities - +endpoint-level validation comes before entity-level. + +**qux tries listing all RBAC users** + +``` +http :8001/teamA/rbac/users/ Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "message": "qux, you do not have permissions to read this resource" +} +``` + +**qux tries listing all Workspaces** + +``` +http :8001/teamA/rbac/workspaces/ Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "message": "qux, you do not have permissions to read this resource" +} +``` + +**qux tries to access service1** + +``` +http :8001/teamA/services/service1 Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "host": "httpbin.konghq.com", + "created_at": 1531066074, + "connect_timeout": 60000, + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43", + "protocol": "http", + "name": "service1", + "read_timeout": 60000, + "port": 80, + "path": null, + "updated_at": 1531066074, + "retries": 5, + "write_timeout": 60000 +} +``` + +Similarly, he can access his Route: + +``` +http :8001/teamA/routes/3ed24101-19a7-4a0b-a10f-2f47bcd4ff43 Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "created_at": 1531066253, + "strip_path": false, + "hosts": null, + "preserve_host": false, + "regex_priority": 0, + "updated_at": 1531066253, + "paths": [ + "/anything" + ], + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "methods": null, + "protocols": [ + "http", + "https" + ], + "id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b" +} +``` + +## Closing Remarks + +We will end this chapter with a few closing remarks. + +### Wildcards in Permissions + +RBAC supports the use of wildcards—represented by the `*` character—in many +aspects of permissions: + +**Creating endpoint permissions—`/rbac/roles/:role/endpoints`** + +To create an endpoint permission, one must pass the parameters below, all of +which can be replaced by a * character: + +- `endpoint`: `*` matches **any endpoint** +- `workspace`: `*` matches **any workspace** +- `actions`: `*` evaluates to **all actions—read, update, create, delete** + +**Special case**: `endpoint`, in addition to a single `*`, also accepts `*` +within the endpoint itself, replacing a URL segment between `/`; for example, +all of the following are valid endpoints: + +- `/rbac/*`: where `*` replaces any possible segment—e.g., `/rbac/users`, +`/rbac/roles`, etc +- `/services/*/plugins`: `*` matches any Service name or ID + +Note, however, that `*` **is not** a generic, shell-like, glob pattern. + +If `workspace` is omitted, it defaults to the current request's workspace. For +example, a role-endpoint permission created with `/teamA/roles/admin/endpoints` +is scoped to workspace `teamA`. + +**Creating entity permissions—`/rbac/roles/:role/entities`** + +Similarly, for entity permissions, the following parameters accept a `*` +character: + +- `entity_id`: `*` matches **any entity ID** + +### Entities Concealing in Entity-Level RBAC + +With Entity-Level RBAC enabled, endpoints that list all entities of a +particular collection will only list entities that the user has access to; +in the example above, if user qux listed all Routes, he would only get as +response the entities he has access to—even though there could be more: + +``` +http :8001/teamA/routes Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "next": null, + "data": [ + { + "created_at": 1531066253, + "id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b", + "hosts": null, + "updated_at": 1531066253, + "preserve_host": false, + "regex_priority": 0, + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "paths": [ + "/anything" + ], + "methods": null, + "strip_path": false, + "protocols": [ + "http", + "https" + ] + } + ] +} +``` + +Some Kong endpoints carry a `total` field in responses; with Entity-Level RBAC +enabled, the global count of entities is displayed, but only entities the user +has access to are themselves shown; for example, if Team A has a number of +plugins configured, but qux only has access to one of them, the following +would be the expected output for a GET request to `/teamA/plugins`: + +``` +http :8001/teamA/plugins Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "total": 2, + "data": [ + { + "created_at": 1531070344000, + "config": { + "key_in_body": false, + "run_on_preflight": true, + "anonymous": "", + "hide_credentials": false, + "key_names": [ + "apikey" + ] + }, + "id": "8813dd0b-3e9d-4bcf-8a10-3112654f86e7", + "name": "key-auth", + "enabled": true + } + ] +} +``` + +Notice the `total` field is 2, but qux only got one entity in the response. + +### Creating Entities in Entity-Level RBAC + +As entity-level RBAC provides access control to individual existing entities, +it does not apply to creation of new entities; for that, endpoint-level +permissions must be configured and enforced. For example, if endpoint-level +permissions are not enforced, qux will be able to create new entities: + +``` +http :8001/teamA/routes paths[]=/anything service.id=3ed24101-19a7-4a0b-a10f-2f47bcd4ff43 strip_path=false Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "created_at": 1531070828, + "strip_path": false, + "hosts": null, + "preserve_host": false, + "regex_priority": 0, + "updated_at": 1531070828, + "paths": [ + "/anything" + ], + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "methods": null, + "protocols": [ + "http", + "https" + ], + "id": "6ee76f74-3c96-46a9-ae48-72df0717d244" +} +``` + +and qux will automatically have permissions to perform any actions to entities +he created. + +--- + +[rbac-overview]: /gateway/{{page.release}}/configure/auth/rbac +[rbac-admin]: /gateway/{{page.release}}/admin-api/rbac/reference +[workspaces-examples]: /gateway/{{page.release}}/admin-api/workspaces/examples +[getting-started-guide]: /gateway/{{page.release}}/get-started/comprehensive diff --git a/app/gateway/2.6.x/admin-api/rbac/reference.md b/app/gateway/2.6.x/admin-api/rbac/reference.md new file mode 100644 index 000000000000..fa59644e1757 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/rbac/reference.md @@ -0,0 +1,950 @@ +--- +title: RBAC Reference +badge: enterprise +--- + +Kong {{site.base_gateway}}'s RBAC feature is configurable through Kong's +[Admin API](/gateway/{{page.release}}/admin-api/) or via the [Kong Manager](/gateway/{{page.release}}/configure/auth/rbac/). + +There are 4 basic entities involving RBAC. + +- **User**: The entity interacting with the system. Can be associated with + zero, one or more roles. Example: user `bob` has token `1234`. +- **Role**: Set of permissions (`role_endpoint` and + `role_entity`). Has a name and can be associated with zero, one or + more permissions. Example: user bob is associated with role + `developer`. +- **role_endpoint**: A set of enabled or disabled (see `negative` + parameter) actions (`read`, `create`, `update`, `delete`) + `endpoint`. Example: Role `developer` has 1 role_endpoint: `read & + write` to endpoint `/routes` +- **role_entity**: A set of enabled or disabled (see `negative` + parameter) actions (`read`, `create`, `update`, `delete`) + `entity`. Example: Role `developer` has 1 role_entity: `read & write + & delete` to entity `283fccff-2d4f-49a9-8730-dc8b71ec2245`. + +## Add a User +**Endpoint** + +
/rbac/users
+ +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `name` | The RBAC user name. | +| `user_token` | The authentication token to be presented to the Admin API. The value will be hashed and cannot be fetched in plaintext. | +| `enabled`
optional | A flag to enable or disable the user. By default, users are enabled. | +| `comment`
optional | A string describing the RBAC user object. | + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "comment": null, + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "doc_knight", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" +} +``` +___ + +## Retrieve a User +**Endpoint** + +
/rbac/users/{name_or_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC user name or UUID. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "doc_lord", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" +} +``` +___ + +## List Users +**Endpoint** + +
/rbac/users/
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "comment": null, + "created_at": 1557512629, + "enabled": true, + "id": "f035f120-a95e-4327-b2ae-8fa264601d75", + "name": "doc_lord", + "user_token": "$2b$09$TIMneYcTosdG9WbzRsqcweAS2zote8g6I8HqXAtbFHR1pds2ymsh6", + "user_token_ident": "88ea3" + }, + { + "comment": null, + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "doc_knight", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" + } + ], + "next": null +} +``` + +⚠️ **Note**: **RBAC Users** associated with **Admins** will _not_ be +listed with **`GET`** `/rbac/users`. Instead, use +[**`GET`** `/admins`](/gateway/{{page.release}}/admin-api/admins/reference/#list-admins) +to list all **Admins**. + +___ + +## Update a User +**Endpoint** + +
/rbac/users/{name_or_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC user name or UUID. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `user_token`
optional | The authentication token to be presented to the Admin API. If this value is not present, the token will automatically be generated. | +| `enabled`
optional | A flag to enable or disable the user. By default, users are enabled. | +| `comment`
optional | A string describing the RBAC user object. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "this comment came from a patch request", + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "donut_lord", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" +} +``` +___ + +## Delete a User +**Endpoint** + +
/rbac/users/{name_or_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC user name or UUID. | + +**Response** + +``` +HTTP 204 No Content +``` +___ + +## Add a Role +**Endpoint** + +
/rbac/roles
+ +| Attribute | Description | +| --------- | ----------- | +| `name` | The RBAC role name. | +| `comment`
optional | A string describing the RBAC user object. | + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "comment": null, + "created_at": 1557532241, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "service_reader" +} +``` +___ + +## Retrieve a Role +Endpoint + +
/rbac/roles/{name_or_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1557532241, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "service_reader" +} +``` +___ + +## List Roles +**Endpoint** + +
/rbac/roles
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "comment": "Full access to all endpoints, across all workspaces—except RBAC Admin API", + "created_at": 1557506249, + "id": "38a03d47-faae-4366-b430-f6c10aee5029", + "name": "admin" + }, + { + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1557506249, + "id": "4141675c-8beb-41a5-aa04-6258ab2d2f7f", + "name": "read-only" + }, + { + "comment": "Full access to all endpoints, across all workspaces", + "created_at": 1557506249, + "id": "888117e0-f2b3-404d-823b-dee595423505", + "name": "super-admin" + }, + { + "comment": null, + "created_at": 1557532241, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "name": "doc_lord" + } + ], + "next": null +} +``` +___ + +## Update or Create a Role +**Endpoint** + +
/rbac/roles/{name_or_id}
+ +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `name` | The RBAC role name. | +| `comment`
optional | A string describing the RBAC user object. | + +The behavior of `PUT` endpoints is the following: if the request +payload **does** contain an entity's primary key, the payload will +"replace" the entity specified by the given primary key. If the +primary key is **not** that of an existing entity, the entity will be +created with the given payload. + +**Response** + +If creating the entity: + +``` +HTTP 201 Created +``` + +If replacing the entity: + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "the best", + "created_at": 1557532566, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "doc_lord" +} +``` + +## Update a Role +**Endpoint** + +
/rbac/roles/{name_or_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role or UUID. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `comment`
optional | A string describing the RBAC role object. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "comment from patch request", + "created_at": 1557532566, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "service_reader" +} +``` +___ + +## Delete a Role +**Endpoint** + +
/rbac/roles/{name_or_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name` | The RBAC role name. | + +**Response** + +``` +HTTP 204 No Content +``` +___ + +## Add a Role Endpoint Permission +**Endpoint** + +
/rbac/roles/{name_or_id}/endpoints
+ + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name. | + + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `workspace` | Workspace tied to the endpoint. Defaults to the default permission. Special value of "*" means **all** workspaces are affected | +| `endpoint` | Endpoint associated with this permission. | +| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this endpoint. By default this value is false. | +| `actions` | One or more actions associated with this permission. This is a comma separated string (read,create,update,delete) | +| `comment`
optional | A string describing the RBAC permission object. | + +`endpoint` must be the path of the associated endpoint. They can be +exact matches, or contain wildcards, represented by `*`. + +- Exact matches; for example: + * /services/ + * /services/foo + +- Wildcards; for example: + * /services/* + * /services/*/plugins + +Where `*` replaces exactly one segment between slashes (or the end of +the path). + +Note that wildcards can be nested (`/rbac/*`, `/rbac/*/*`, +`/rbac/*/*/*` would refer to all paths under `/rbac/`) + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764505, + "endpoint": "/consumers", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" +} +``` + +--- + +## Retrieve a Role Endpoint Permission +**Endpoint** + +
/rbac/roles/{name_or_id}/endpoints/{workspace_name_or_id}/{endpoint}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `workspace_name_or_id` | The workspace name or UUID. | +| `endpoint` | The endpoint associated with this permission. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764505, + "endpoint": "/consumers", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" +} +``` + +--- + + + +## List Role Endpoints Permissions +**Endpoint** + +
/rbac/roles/{role_name_or_id}/endpoints
+ +| Attribute | Description | +| --------- | ----------- | +| `role_name_or_id` | The RBAC role name or UUID. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764505, + "endpoint": "/consumers", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" + }, + { + "actions": [ + "read" + ], + "created_at": 1557764438, + "endpoint": "/services", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" + } + ] +} +``` + +--- + +## Update a Role Endpoint Permission +**Endpoint** + +
/rbac/roles/{name_or_id}/endpoints/{workspace_name_or_id}/{endpoint}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `workspace_name_or_id` | The workspace name or UUID. | +| `endpoint` | The endpoint associated with this permission. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. | +| `actions` | One or more actions associated with this permission. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764438, + "endpoint": "/services", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" +} +``` + +--- + + + +## Delete a Role Endpoint Permission +**Endpoint** + +
/rbac/roles/{name_or_id}/endpoints/{workspace_name_or_id}/{endpoint}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `workspace_name_or_id` | The workspace name or UUID. | +| `endpoint` | The endpoint associated with this permission. | + +**Response** + +``` +HTTP 204 No Content +``` + +--- + + + +## Add a Role Entity Permission +**Endpoint** +
/rbac/roles/{name_or_id}/entities
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. | +| `entity_id` | id of the entity associated with this permission. +| `entity_type` | Type of the entity of a given `entity_id`. | +| `actions` | One or more actions associated with this permission. | +| `comment`
optional | A string describing the RBAC permission object | + +`entity_id` must be the ID of an entity in Kong; if the ID of a +workspace is given, the permission will apply to all entities in that +workspace. Future entities belonging to that workspace will get the +same permissions. A wildcard `*` will be interpreted as **all +entities** in the system. + + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "actions": [ + "delete", + "create", + "read" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } +} +``` + +--- + +## Retrieve a Role Entity Permission +**Endpoint** +
/rbac/roles/{name_or_id}/entities/{entity_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC permission name or UUID. | +| `entity_id` | id of the entity associated with this permission. | + +**Response** + +``` +HTTP 200 Ok +``` + +```json +{ + "actions": [ + "delete", + "create", + "read" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } +} +``` + +--- + +## List Entity Permissions + +**Endpoint** +
/rbac/roles/{name_or_id}/entities
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC permission name or UUID. | + +**Response** + +``` +HTTP 200 Ok +``` + +```json +{ + "data": [ + { + "actions": [ + "delete", + "create", + "read" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } + } + ] +} +``` + +--- +## Update an Entity Permission +**Endpoint** + +
/rbac/roles/{name_or_id}/entities/{entity_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `entity_id` | The entity name or UUID. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. | +| `actions` | One or more actions associated with this permission. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "actions": [ + "update" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } +} +``` + +--- + +## Delete an Entity Permission +**Endpoint** + +
/rbac/roles/{name_or_id}/entities/{entity_id}
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `entity_id` | The entity name or UUID. | + +**Response** + +``` +HTTP 204 No Content +``` + +--- + +## List Role Permissions +**Endpoint** +
/rbac/roles/{name_or_id}/permissions/
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + + +**Response** + +``` +HTTP 200 OK +``` +```json +{ + "endpoints": { + "*": { + "*": { + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": false + }, + "/*/rbac/*": { + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": true + } + } + }, + "entities": {} +} +``` + +## Add a User to a Role +**Endpoint** + +
/rbac/users/{name_or_id}/roles
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `roles` | Comma-separated list of role names to assign to the user. | + +**Response** + +``` +HTTP 201 Created +``` +```json +{ + "roles": [ + { + "created_at": 1557772263, + "id": "aae80073-095f-4553-ba9a-bee5ed3b8b91", + "name": "doc-knight" + } + ], + "user": { + "comment": null, + "created_at": 1557772232, + "enabled": true, + "id": "b65ca712-7ceb-4114-87f4-5c310492582c", + "name": "gruce-wayne", + "user_token": "$2b$09$gZnMKK/mm/d2rAXN7gL63uL43mjdX/62iwMqdyCQwLyC0af3ce/1K", + "user_token_ident": "88ea3" + } +} +``` + +--- +## List a User's Roles +**Endpoint** + +
/rbac/users/{name_or_id}/roles
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + + +**Response** + +``` +HTTP 200 OK +``` +```json + +{ + "roles": [ + { + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1557765500, + "id": "a1c810ee-8366-4654-ba0c-963ffb9ccf2e", + "name": "read-only" + }, + { + "created_at": 1557772263, + "id": "aae80073-095f-4553-ba9a-bee5ed3b8b91", + "name": "doc-knight" + } + ], + "user": { + "comment": null, + "created_at": 1557772232, + "enabled": true, + "id": "b65ca712-7ceb-4114-87f4-5c310492582c", + "name": "gruce-wayne", + "user_token": "$2b$09$gZnMKK/mm/d2rAXN7gL63uL43mjdX/62iwMqdyCQwLyC0af3ce/1K", + "user_token_ident": "88ea3" + } +} +``` + +--- +## Delete a Role from a User +**Endpoint** + +
/rbac/users/{name_or_id}/roles
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `roles` | Comma-separated list of role names to assign to the user. | + +**Response** + +``` +HTTP 204 No Content +``` + +--- + +## List a User's Permissions +**Endpoint** + +
/rbac/users/{name_or_id}/permissions
+ +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + +**Response** + +``` +HTTP 200 OK +``` +```json +{ + "endpoints": { + "*": { + "*": { + "actions": [ + "read" + ], + "negative": false + } + } + }, + "entities": {} +} + +``` diff --git a/app/gateway/2.6.x/admin-api/secure-admin-api.md b/app/gateway/2.6.x/admin-api/secure-admin-api.md new file mode 100644 index 000000000000..c40d7db8f078 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/secure-admin-api.md @@ -0,0 +1,245 @@ +--- +title: Securing the Admin API +--- + +{{site.base_gateway}}'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`. + +### 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. + +## 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, let's assume that Kong `admin_listen` is `127.0.0.1:8001`, so it is only +available from localhost. The port `8000` is serving proxy traffic, presumably exposed via +`myhost.dev:8000` + +We want to expose Admin API via the url `:8000/admin-api`, in a controlled way. We can do so by +creating a Service and Route for it from inside `127.0.0.1`: + +```bash +curl -X POST http://127.0.0.1:8001/services \ + --data name=admin-api \ + --data host=127.0.0.1 \ + --data port=8001 + +curl -X POST http://127.0.0.1:8001/services/admin-api/routes \ + --data paths[]=/admin-api +``` + +We can now transparently reach the Admin API through the proxy server, from outside `127.0.0.1`: + +```bash +curl myhost.dev:8000/admin-api/services +{ + "data":[ + { + "id": "653b21bd-4d81-4573-ba00-177cc0108dec", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "admin-api", + "retries": 5, + "protocol": "http", + "host": "127.0.0.1", + "port": 8001, + "path": "/admin-api", + "connect_timeout": 60000, + "write_timeout": 60000, + "read_timeout": 60000 + } + ], + "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. + +If you are using Docker to host {{site.ee_product_name}}, you can accomplish a similar task using a declarative configuration such as this one: + +``` yaml +_format_version: "1.1" + +services: +- name: admin-api + url: http://127.0.0.1:8001 + routes: + - paths: + - /admin-api + plugins: + - name: key-auth + +consumers: +- username: admin + keyauth_credentials: + - key: secret +``` + +Under this configuration, the Admin API will be available through the `/admin-api`, but only for requests accompanied with `?apikey=secret` query +parameters. + +Assuming that the file above is stored in `$(pwd)/kong.yml`, a DB-less {{site.ee_product_name}} can use it as it starts like this: + +``` bash +docker run -d --name kong-ee \ + -e "KONG_DATABASE=off" \ + -e "KONG_DECLARATIVE_CONFIG=/home/kong/kong.yml" + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + -v $(pwd):/home/kong + kong-ee +``` + +With a PostgreSQL database, the initialization steps would be the following: + +``` bash +# Start PostgreSQL on a Docker container +# Notice that PG_PASSWORD needs to be set +docker run --name kong-ee-database \ + -p 5432:5432 \ + -e "POSTGRES_USER=kong" \ + -e "POSTGRES_DB=kong" \ + -e "POSTGRES_PASSWORD=$PG_PASSWORD" \ + -d postgres:9.6 + +# Run Kong migrations to initialize the database +docker run --rm \ + --link kong-ee-database:kong-ee-database \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=$PG_PASSWORD" \ + kong-ee kong migrations bootstrap + +# Load the configuration file which enables the Admin API loopback +# Notice that it is assumed that kong.yml is located in $(pwd)/kong.yml +docker run --rm \ + --link kong-ee-database:kong-ee-database \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=$PG_PASSWORD" \ + -v $(pwd):/home/kong \ + kong-ee kong config db_import /home/kong/kong.yml + +# Start Kong +docker run -d --name kong \ + --link kong-ee-database:kong-ee-database \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=$PG_PASSWORD" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + kong-ee +``` + +In both cases, once Kong is up and running, the Admin API would be available but protected: + +``` bash +curl myhost.dev:8000/admin-api/services +=> HTTP/1.1 401 Unauthorized + +curl myhost.dev:8000/admin-api/services?apikey=secret +=> HTTP/1.1 200 OK +{ + "data": [ + { + "ca_certificates": null, + "client_certificate": null, + "connect_timeout": 60000, + ... + } + ] +} +``` + +## 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]. + +## Role Based Access Control +{:.badge .enterprise} + +{{site.base_gateway}} users can configure [role-based access control](/gateway/{{page.release}}/configure/auth/rbac/) +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. + +[acl]: /hub/kong-inc/acl +[basic-auth]: /hub/kong-inc/basic-auth +[custom-configuration]: /gateway/{{page.release}}/reference/configuration/#custom-nginx-configuration +[ip-restriction]: /hub/kong-inc/ip-restriction +[key-auth]: /hub/kong-inc/key-auth diff --git a/app/gateway/2.6.x/admin-api/workspaces/examples.md b/app/gateway/2.6.x/admin-api/workspaces/examples.md new file mode 100644 index 000000000000..70878fc98d0d --- /dev/null +++ b/app/gateway/2.6.x/admin-api/workspaces/examples.md @@ -0,0 +1,188 @@ +--- +title: Workspace Examples +badge: enterprise +--- + +This chapter aims to provide a step-by-step tutorial on how to set up +workspaces, entities, and see it in action. + +## Important Note: Conflicting Services or Routes in workspaces + +Workspaces provide a way to segment Kong entities—entities in a workspace +are isolated from those in other workspaces. That said, entities +such as Services and Routes have "routing rules", which are pieces of info +attached to Services or Routes—such as HTTP method, URI, or host—that allow a +given proxy-side request to be routed to its corresponding upstream service. + +Admins configuring Services (or Routes) in their workspaces do not want traffic +directed to their Services or Routes to be swallowed by Services or Routes in other +workspaces; Kong allows them to prevent such undesired behavior—as long as +certain measures are taken. Below we outline the conflict detection algorithm +used by Kong to determine if a conflict occurs. + +* At Service or Route **creation or modification** time, Kong runs its internal +router: + - If no Services or Routes are found with matching routing rules, the creation + or modification proceeds + - If Services or Routes with matching routing rules are found **within the same + workspace**, proceed + - If Services or Routes are found **in a different workspace**: + * If the matching Service or Route **does not have an associated + `host` value**—`409 Conflict` + * If the matching Service or Route's `host` is a wildcard + - If they are the same, a conflict is reported—`409 Conflict` + - If they are not equal, proceed + * If the matching Service or Route's `host` is an absolute value, a + conflict is reported—`409 Conflict` + +## The Default workspace + +Kong creates a default workspace—unsurprisingly named `default`—whose goal +is to group all existing entities in Kong, where "existing entities" refers to: + +- Entities that were created in operation in previous versions & in case +one is migrating from an older Kong version; +- Entities that Kong creates at migration time—e.g., RBAC credentials, which +are provisioned at migration time as a convenience + +It will also hold entities that are created without being explicitly assigned to +a specific workspace. + +That said, it's worth noting that the default workspace is a workspace as any +other, the only difference being that it's created by Kong, at migration time. + +(Examples will be shown using the HTTPie command line client.) + +## Listing workspaces and its entities + +In a fresh {{site.base_gateway}} install, submit the +following request: + +``` +http GET :8001/workspaces +{ + "total": 1, + "data": [ + { + "created_at": 1529627841000, + "id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "name": "default" + } + ] +} +``` + +## Creating a workspace + +A more interesting example would be segmenting entities by teams; for the sake of +example, let's say they are teamA, teamB, and teamC. + +Each of these teams has its own set of entities—say, upstream services and +routes—and want to segregate their configurations and traffic; they can +achieve that with workspaces. + +``` +http POST :8001/workspaces name=teamA +{ + "created_at": 1528843468000, + "id": "735af96e-206f-43f7-88f0-b930d5fd4b7e", + "name": "teamA" +} +``` + +``` +http POST :8001/workspaces name=teamB +{ + "name": "teamB", + "created_at": 1529628574000, + "id": "a25728ac-6036-497c-82ee-524d4c22fcae" +} +``` + +``` +http POST :8001/workspaces name=teamC +{ + "name": "teamC", + "created_at": 1529628622000, + "id": "34b28f10-e1ec-4dad-9ac0-74780baee182" +} +``` + +At this point, if we list workspaces, we will get a total of 4—remember, +Kong provisions a "default" workspace and, on top of that, we created other +3. + +``` +{ + "data": [ + { + "created_at": 1529627841000, + "id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "name": "default" + }, + { + "created_at": 1529628818000, + "id": "5ed1c043-78cc-4fe2-924e-40b17ecd97bc", + "name": "teamA" + }, + { + "created_at": 1529628574000, + "id": "a25728ac-6036-497c-82ee-524d4c22fcae", + "name": "teamB" + }, + { + "created_at": 1529628622000, + "id": "34b28f10-e1ec-4dad-9ac0-74780baee182", + "name": "teamC" + } + ] + "total": 4, +} + +``` + +## Entities in different workspaces can have the same name! + +Different teams—belonging to different workspaces—are allowed to give any +name to their entities. To provide an example of that, let's say that Teams A, B, +and C want a particular consumer named `guest`—a different consumer for each +team, sharing the same username. + +``` +http :8001/teamA/consumers username=guest +{ + "created_at": 1529703386000, + "id": "2e230275-2a4a-41fd-b06b-bae37008aed2", + "type": 0, + "username": "guest" +} +``` + +``` +http :8001/teamB/consumers username=guest +{ + "created_at": 1529703390000, + "id": "8533e404-8d56-4481-a919-0ee35b8a768c", + "type": 0, + "username": "guest" +} +``` + +``` +http :8001/teamC/consumers username=guest +{ + "created_at": 1529703393000, + "id": "5fb180b0-0cd0-42e1-8d75-ce42a54b2909", + "type": 0, + "username": "guest" +} +``` + +With this, Teams A, B, and C will have the freedom to operate their `guest` +consumer independently, choosing authentication plugins or doing any other +operation that is allowed in the non-workspaced Kong world. + + +--- + +[services]: /gateway/{{page.release}}/admin-api/#service-object diff --git a/app/gateway/2.6.x/admin-api/workspaces/reference.md b/app/gateway/2.6.x/admin-api/workspaces/reference.md new file mode 100644 index 000000000000..7403198c7128 --- /dev/null +++ b/app/gateway/2.6.x/admin-api/workspaces/reference.md @@ -0,0 +1,352 @@ +--- +title: Workspaces Reference +badge: enterprise + +workspace_body: | + Attribute | Description + ---:| --- + `name` | The **Workspace** name. +--- + + +{{site.base_gateway}}'s Workspaces feature is configurable through Kong's +Admin API. + +## Workspace Object + +The **Workspace** object describes the **Workspace** entity, which has an ID +and a name. + +### Add Workspace + +**Endpoint** + +
/workspaces/
+ +#### Request Body + +{{ page.workspace_body }} + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557441226, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "green-team" +} +``` + +### List Workspaces + +**Endpoint** + +
/workspaces/
+ +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557419951, + "id": "00000000-0000-0000-0000-000000000000", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "default" + }, + { + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557441226, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "green-team" + } + ], + "next": null +} +``` + +### Update or Create a Workspace + +**Endpoint** + +
/workspaces/{id}
+ +Attributes | Description +---:| --- +`id`
**conditional** | The **Workspace's** unique ID, if replacing it.* + +* The behavior of `PUT` endpoints is the following: if the request payload **does +not** contain an entity's primary key (`id` for Workspaces), the entity will be +created with the given payload. If the request payload **does** contain an +entity's primary key, the payload will "replace" the entity specified by the +given primary key. If the primary key is **not** that of an existing entity, `404 +NOT FOUND` will be returned. + +#### Request Body + +Attribute | Description +---:| --- +`name` | The **Workspace** name. + +**Response** + +If creating the entity: + +``` +HTTP 201 Created +``` + +If replacing the entity: + +``` +HTTP 200 OK +``` + +```json +{ + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557504202, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "rocket-team" +} +``` + +### Retrieve a Workspace + +**Endpoint** + +
/workspaces/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the **Workspace** to retrieve + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "config": { + "portal": false, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]" + }, + "created_at": 1557504202, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { }, + "name": "rocket-team" +} +``` + +### Retrieve Workspace Metadata + +#### Endpoint + +
/workspaces/{name or id}/meta
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the **Workspace** to retrieve + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "counts": { + "acls": 1, + "basicauth_credentials": 1, + "consumers": 1234, + "files": 41, + "hmacauth_credentials": 1, + "jwt_secrets": 1, + "keyauth_credentials": 1, + "oauth2_authorization_codes": 1, + "oauth2_credentials": 1, + "oauth2_tokens": 1, + "plugins": 5, + "rbac_roles": 3, + "rbac_users": 12, + "routes": 15, + "services": 2, + "ssl_certificates": 1, + "ssl_servers_names": 1, + "targets": 1, + "upstreams": 1 + } +} +``` + +### Delete a Workspace + +**Endpoint** + +
/workspaces/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the **Workspace** to delete + +**Note:** All entities within a **Workspace** must be deleted before the +**Workspace** itself can be. + +**Response** + +``` +HTTP 204 No Content +``` + +### Update a Workspace + +**Endpoint** + +
/workspaces/{name or id}
+ +Attributes | Description +---:| --- +`name or id`
**required** | The unique identifier **or** the name of the **Workspace** to patch + +#### Request Body + +Attributes | Description +---:| --- +`comment` | A string describing the **Workspace** + +The behavior of `PATCH` endpoints prevents the renaming of a **Workspace**. + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "this is a sample comment in the patch request", + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557509909, + "id": "c543d2c8-d297-4c9c-adf5-cd64212868fd", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "green-team" +} +``` +--- + +[Admin API]: /gateway/{{page.release}}/admin-api/ diff --git a/app/gateway/2.6.x/compatibility.md b/app/gateway/2.6.x/compatibility.md new file mode 100644 index 000000000000..32ed9c832303 --- /dev/null +++ b/app/gateway/2.6.x/compatibility.md @@ -0,0 +1,37 @@ +--- +title: Kong Gateway Compatibility +--- + +Provided below are compatibility tables for {{site.base_gateway}}. Select a version +to see technologies that have been tested for interoperability with the Kong platform. + +Please see [{{site.base_gateway}} Version Support](/gateway/latest/support-policy/) +for more information about Kong's support for {{site.base_gateway}} and our +[Support & Maintenance Policy](https://konghq.com/supportandmaintenancepolicy). + +{% assign compat_data = site.data.tables.compat[page.release.value] %} + +{% unless compat_data %} +{% assign msg = "compat.json data is missing for Gateway " | append: page.release %} +{{ msg | raise_error }} +{% endunless %} + +

If you need help using {{site.base_gateway}} with any of the supported technologies, ask a question in our community.

+ +

If you have an Enterprise tier subscription, contact Kong Support.

+ +

Supported operating systems

+
    +{% for system in compat_data.os %} +
  • {{ system[0] | split: "-" | join: " " | capitalize }}: {{ system[1] }}
  • +{% endfor %} + +Kong only supports the latest vendor-supported minor version for RHEL and CentOS. +
+ +

Supported databases

+
    +{% for db in compat_data.databases %} +
  • {{ db[0] | capitalize }}: {{ db[1] }}
  • +{% endfor %} +
diff --git a/app/gateway/2.6.x/configure/auth/allowing-multiple-authentication-methods.md b/app/gateway/2.6.x/configure/auth/allowing-multiple-authentication-methods.md new file mode 100644 index 000000000000..9702f70cbdd2 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/allowing-multiple-authentication-methods.md @@ -0,0 +1,108 @@ +--- +title: Allowing Multiple Authentication Methods +--- + +The default behavior for Kong authentication plugins is to require credentials +for all requests without regard for whether a request has been authenticated +via some other plugin. Configuring an anonymous consumer on your authentication +plugins allows you to offer clients multiple options for authentication. + +To begin, [create a Service](/gateway/{{page.release}}/admin-api/#service-object) and then create three consumers: + +```bash +curl -sX POST localhost:8001/consumers \ + -H "Content-Type: application/json" \ + --data '{"username": "anonymous"}' + +# {"created_at":1517528237000,"username":"anonymous","id":"d955c0cb-1a6e-4152-9440-414ebb8fee8a"} + +curl -sX POST localhost:8001/consumers \ + -H "Content-Type: application/json" \ + --data '{"username": "medvezhonok"}' + +# {"created_at":1517528259000,"username":"medvezhonok","id":"b3c95318-a932-4bb2-9d74-1298a3ffc87c"} + +curl -sX POST kong-admin:8001/consumers \ + -H "Content-Type: application/json" \ + --data '{"username": "ezhik"}' + +# {"created_at":1517528266000,"username":"ezhik","id":"47e74a17-dc08-4786-a8cf-d8e4f38a5459"} +``` + +The `anonymous` consumer does not correspond to any real user, and will only serve as a fallback. + +Next, we add both Key Auth and Basic Auth plugins to our consumer, and set the anonymous fallback to the consumer we created earlier. + +```bash +curl -sX POST kong-admin:8001/services/example-service/plugins/ \ + -H "Content-Type: application/json" \ + --data '{"name": "key-auth", "config": { "hide_credentials": true, "anonymous": "d955c0cb-1a6e-4152-9440-414ebb8fee8a"} }' + +# {"created_at":1517528304000,"config":{"key_in_body":false,"hide_credentials":true,"anonymous":"d955c0cb-1a6e-4152-9440-414ebb8fee8a","run_on_preflight":true,"key_names":["apikey"]},"id":"bb884f7b-4e48-4166-8c80-c858b5a4c357","name":"key-auth","service_id":"a2a168a8-4491-4fe1-9426-cde3b5fcd45b","enabled":true} + +curl -sX POST kong-admin:8001/services/example-service/plugins/ \ + -H "Content-Type: application/json" \ + --data '{"name": "basic-auth", "config": { "hide_credentials": true, "anonymous": "d955c0cb-1a6e-4152-9440-414ebb8fee8a"} }' + +# {"created_at":1517528499000,"config":{"hide_credentials":true,"anonymous":"d955c0cb-1a6e-4152-9440-414ebb8fee8a"},"id":"e5a40543-debe-4225-a879-a54901368e6d","name":"basic-auth","service_id":"a2a168a8-4491-4fe1-9426-cde3b5fcd45b","enabled":true} +``` + +If using [OpenID Connect](/hub/kong-inc/openid-connect/), you must also set `config.consumer_claim` along with `anonymous`, as setting `anonymous` alone will not map that consumer. + +At this point unauthenticated requests and requests with invalid credentials are still allowed. The anonymous consumer is allowed, and will be applied to any request that does not pass a set of credentials associated with some other consumer. + +```bash +curl -s example.com:8000/user-agent + +# {"user-agent": "curl/7.58.0"} + +curl -s example.com:8000/user-agent?apikey=nonsense + +# {"user-agent": "curl/7.58.0"} +``` + +We'll now add a Key Auth credential for one consumer, and a Basic Auth credential for another. + +```bash +curl -sX POST kong-admin:8001/consumers/medvezhonok/basic-auth \ + -H "Content-Type: application/json" \ + --data '{"username": "medvezhonok", "password": "hunter2"}' + +# {"created_at":1517528647000,"id":"bb350b87-f0d2-4605-b997-e28a116d8b6d","username":"medvezhonok","password":"f239a0404351d7170201e7f92fa9b3159e47bb01","consumer_id":"b3c95318-a932-4bb2-9d74-1298a3ffc87c"} + +curl -sX POST kong-admin:8001/consumers/ezhik/key-auth \ + -H "Content-Type: application/json" \ + --data '{"key": "hunter3"}' + +# {"id":"06412d6e-8d41-47f7-a911-3c821ec98f1b","created_at":1517528730000,"key":"hunter3","consumer_id":"47e74a17-dc08-4786-a8cf-d8e4f38a5459"} +``` + +Lastly, we add a Request Terminator to the anonymous consumer. + +```bash +curl -sX POST kong-admin:8001/consumers/d955c0cb-1a6e-4152-9440-414ebb8fee8a/plugins/ \ + -H "Content-Type: application/json" \ + --data '{"name": "request-termination", "config": { "status_code": 401, "content_type": "application/json; charset=utf-8", "body": "{\"error\": \"Authentication required\"}"} }' + +# {"created_at":1517528791000,"config":{"status_code":401,"content_type":"application\/json; charset=utf-8","body":"{\"error\": \"Authentication required\"}"},"id":"21fc5f6f-363f-4d79-b533-ce26d4478879","name":"request-termination","enabled":true,"consumer_id":"d955c0cb-1a6e-4152-9440-414ebb8fee8a"} +``` + +Requests with missing or invalid credentials are now rejected, whereas authorized requests using either authentication method are allowed. + +```bash +curl -s example.com:8000/user-agent?apikey=nonsense + +# {"error": "Authentication required"} + +curl -s example.com:8000/user-agent + +# {"error": "Authentication required"} + +curl -s example.com:8000/user-agent?apikey=hunter3 + +# {"user-agent": "curl/7.58.0"} + +curl -s example.com:8000/user-agent -u medvezhonok:hunter2 + +# {"user-agent": "curl/7.58.0"} +``` diff --git a/app/gateway/2.6.x/configure/auth/index.md b/app/gateway/2.6.x/configure/auth/index.md new file mode 100644 index 000000000000..3c2c57580d76 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/index.md @@ -0,0 +1,213 @@ +--- +title: Authentication Reference +--- + +Traffic to your Upstream services (APIs or microservices) is typically controlled by the application and +configuration of various Kong [authentication plugins][plugins]. Because 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 behavior. +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 `httpbin.konghq.com`, which will echo + the request: + + ```bash + $ curl -i -X POST \ + --url http://localhost:8001/services/ \ + --data 'name=example-service' \ + --data 'url=https://httpbin.konghq.com/anything' + ``` + + 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 use 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 httpbin 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 use 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 and so forth will require authentication by the other configured auth plugins. + +{:.important} +When multiple authentication plugins are enabled in an `OR` fashion on a given service, +and you want anonymous access to be forbidden, then the [Request Termination plugin](/hub/kong-inc/request-termination/) should be +configured on the anonymous consumer. +Failure to do so will allow unauthorized requests. + +[plugins]: /hub/ +[key-auth]: /hub/kong-inc/key-auth diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/basic.md b/app/gateway/2.6.x/configure/auth/kong-manager/basic.md new file mode 100644 index 000000000000..3a87f9154c71 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/basic.md @@ -0,0 +1,41 @@ +--- +title: Enable Basic Auth for Kong Manager +badge: enterprise +--- + +### Prerequisites + +To enable Basic Authentication, configure Kong with the following properties: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { "secret":"set-your-string-here" } +``` + +The **Sessions Plugin** requires a secret and is configured securely by default. + +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#session-security), and see [example configurations](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +## Step 1 + +Start Kong: + +``` +$ kong start [-c /path/to/kong/conf] +``` + +## Step 2 + +If you created a **Super Admin** via database migration, log in to Kong +Manager with the username `kong_admin` and the password +set in the environment variable. + +If you created a Super Admin via the Kong Manager "Organization" tab +as described in +[How to Create a Super Admin](/gateway/{{page.release}}/configure/auth/kong-manager/super-admin), +log in with the credentials you created after accepting the email +invitation. diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/email.md b/app/gateway/2.6.x/configure/auth/kong-manager/email.md new file mode 100644 index 000000000000..e58c6365480f --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/email.md @@ -0,0 +1,23 @@ +--- +title: Configuring Kong Manager to Send Email +badge: enterprise +--- + +A **Super Admin** can invite other **Admins** to register in Kong Manager, and **Admins** +can reset their passwords using "Forgot Password" functionality. Both of these +workflows use email to communicate with the user. + +Emails from Kong Manager require the following configuration: + +* [`admin_emails_from`](/gateway/{{page.release}}/reference/configuration/#admin_emails_from) +* [`admin_emails_reply_to`](/gateway/{{page.release}}/reference/configuration/#admin_emails_reply_to) +* [`admin_invitation_expiry`](/gateway/{{page.release}}/reference/configuration/#admin_invitation_expiry) + +Kong does not check for the validity of email +addresses set in the configuration. If the SMTP settings are +configured incorrectly, e.g., if they point to a non-existent +email address, Kong Manager will _not_ display an error message. + +For additional information about SMTP, refer to the +[general SMTP configuration](/gateway/{{page.release}}/reference/configuration/#general-smtp-configuration) +shared by Kong Manager and Dev Portal. diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/index.md b/app/gateway/2.6.x/configure/auth/kong-manager/index.md new file mode 100644 index 000000000000..052fc94d71e6 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/index.md @@ -0,0 +1,66 @@ +--- +title: Securing Kong Manager +badge: enterprise +--- + +Kong Manager enables users with Admin accounts to access Kong entities such +as Services, Plugins, and Consumers. + +The following document summarizes Kong Manager's controls for *authentication* +and *authorization*. + +## Configuring Authentication + +{{site.base_gateway}} comes packaged with Authentication Plugins that can be used +to secure Kong Manager. Unlike enabling a Plugin on an entity or cluster, +enabling an Authentication Plugin for *only* Kong Manager requires turning +on `enforce_rbac`, setting `admin_gui_auth` to the desired type, proper +configuration of `admin_gui_session_conf`, and configuring `admin_gui_auth_conf` +if needed. + +Kong Manager currently supports the following Authentication Plugins: + +* [Basic Auth](/gateway/{{page.release}}/configure/auth/kong-manager/basic/) +* [OIDC](/gateway/{{page.release}}/configure/auth/kong-manager/oidc/) +* [LDAP](/gateway/{{page.release}}/configure/auth/kong-manager/ldap/) + +In addition to the Authentication Plugins above, the new +[Sessions Plugin](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/) +is now required when RBAC is enabled. It sends HTTP cookies to authenticate +client requests and maintain session information. + +The Sessions Plugin requires a secret and is configured +securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, +`cookie_samesite` must be set to `off`. +Learn more about these properties in +[Session Security in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#session-security), +and see [example configurations](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +## Access Control with Roles and Workspaces + +An Admin belongs to a Workspace and should have at least one Role +with a set of Permissions. If an Admin is in a Workspace *without* +a Role, they will not have the ability to see or interact with anything. + +By creating separate +[Workspaces](/gateway/{{page.release}}/configure/auth/kong-manager/workspaces/), + an organization with multiple teams can segment its Kong cluster so that + different teams do not have access to each other's Kong entities. + +{{site.base_gateway}} implements Role-Based Access Control +([RBAC](/gateway/{{page.release}}/configure/auth/rbac/)). +Admins are assigned Roles that have clearly defined Permissions. A +Super Admin has the ability to: + +* Further customize Permissions +* Create entirely new Roles +* Invite or deactivate Admins +* Assign or revoke their Roles + +In Kong Manager, limiting Permissions also restricts the visibility of the +application interface and navigation. Learn more about RBAC in Kong Manager in +our guide +[RBAC in Kong Manager](/gateway/{{page.release}}/configure/auth/rbac/). diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/ldap.md b/app/gateway/2.6.x/configure/auth/kong-manager/ldap.md new file mode 100644 index 000000000000..b8b5225740b7 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/ldap.md @@ -0,0 +1,67 @@ +--- +title: Enable LDAP for Kong Manager +badge: enterprise +--- + +{{site.base_gateway}} offers the ability to bind authentication for Kong Manager +*Admins* to a company's Active Directory using the +[LDAP Authentication Advanced plugin](/hub/kong-inc/ldap-auth-advanced). + +Using the configuration below, it is unnecessary to +manually apply the LDAP plugin; the configuration alone will enable LDAP +Authentication for Kong Manager. + +## Enable LDAP + +Ensure Kong is configured with the following properties either in the +configuration file or using environment variables: + +``` +admin_gui_auth = ldap-auth-advanced +enforce_rbac = on +admin_gui_session_conf = { "secret":"set-your-string-here" } +admin_gui_auth_conf = { \ + "anonymous":"", \ + "attribute":"", \ + "bind_dn":"", \ + "base_dn":"", \ + "cache_ttl": 2, \ + "consumer_by":["username", "custom_id"], \ + "header_type":"Basic", \ + "keepalive":60000, \ + "ldap_host":"", \ + "ldap_password":"", \ + "ldap_port":389, \ + "start_tls":false, \ + "timeout":10000, \ + "verify_ldap_host":true \ +} +``` + +* `"attribute":""`: The attribute used to identify LDAP users + * For example, to map LDAP users to admins by their username, `"attribute":"uid"` +* `"bind_dn":""`: LDAP Bind DN (Distinguished Name) + * Used to perform LDAP search of user. This `bind_dn` should have permissions to search + for the user being authenticated. + * For example, `uid=einstein,ou=scientists,dc=ldap,dc=com` +* `"base_dn":""`: LDAP Base DN (Distinguished Name) + * For example, `ou=scientists,dc=ldap,dc=com` +* `"ldap_host":""`: LDAP host domain + * For example, `"ec2-XX-XXX-XX-XXX.compute-1.amazonaws.com"` +* `"ldap_password":""`: LDAP password + * *Note*: As with any configuration property, sensitive information may be set as an + environment variable instead of being written directly in the configuration file. + +The **Sessions Plugin** requires a secret and is configured securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#session-security), and see [example configurations](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +After starting Kong with the desired configuration, you can create new *Admins* +whose usernames match those in the AD. Those users will then be able to accept +invitations to join Kong Manager and log in with their LDAP credentials. + +### Using Service Directory Mapping on the CLI + +{% include /md/gateway/ldap-service-directory-mapping.md %} diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/networking.md b/app/gateway/2.6.x/configure/auth/kong-manager/networking.md new file mode 100644 index 000000000000..50c7d72d3cf0 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/networking.md @@ -0,0 +1,106 @@ +--- +title: Default and Custom Networking Configuration for Kong Manager +badge: enterprise +--- + +## Default Configuration + +By default, Kong Manager starts up without authentication (see +[`admin_gui_auth`]), and it assumes that the Admin API is available +on port 8001 (see [Default Ports](/gateway/{{page.release}}/plan-and-deploy/default-ports/) of the same host that serves +Kong Manager. + +## Custom Configuration + +Common configurations to enable are + +* Serving Kong Manager from a dedicated Kong node + + When Kong Manager is on a dedicated Kong node, it must make + external calls to the Admin API. Set [`admin_api_uri`] to the + location of your Admin API. + +* Securing Kong Manager through a **Kong Authentication Plugin** + + When Kong Manager is **secured through an Authentication Plugin** + and _not_ on a dedicated node, it makes calls to the Admin API on + the same host. By default, the Admin API listens on ports 8001 and + 8444 on localhost. Change [`admin_listen`] if necessary, or set + [`admin_api_uri`]. + +{% include_cached /md/admin-listen.md release=page.release desc='short' %} + +* Securing Kong Manager and serving it from a dedicated node + + When Kong Manager is **secured and served from a dedicated node**, + set [`admin_api_uri`] to the location of the Admin API. + +The table below summarizes which properties to set (or defaults to +verify) when configuring Kong Manager connectivity to the Admin API. + +| authentication enabled | local API | remote API | auth settings | +|------------------------|--------------|---------------|---------------------------------------------------| +| yes | [`admin_listen`] | [`admin_api_uri`] | [`admin_gui_auth`], [`enforce_rbac`], [`admin_gui_auth_conf`], [`admin_gui_session_conf`] | +| no | [`admin_listen`] | [`admin_api_uri`] | n/a | + +To enable authentication, configure the following properties: + +* [`admin_gui_auth`] set to the desired plugin +* [`admin_gui_auth_conf`] (optional) +* [`admin_gui_session_conf`] set to the desired configuration +* [`enforce_rbac`] set to `on` + +{:.important} +> **Important:** When Kong Manager authentication is enabled, RBAC must be turned +on to enforce authorization rules. Otherwise, whoever can log in +to Kong Manager can perform any operation available on the Admin API. + +## TLS Certificates + +By default, if Kong Manager’s URL is accessed over HTTPS _without_ a certificate issued by a CA, it will +receive a self-signed certificate that modern web browsers will not trust, preventing the application +from accessing the Admin API. + +In order to serve Kong Manager over HTTPS, use a trusted certificate authority to issue TLS certificates, +and have the resulting `.crt` and `.key` files ready for the next step. + +1) Move `.crt` and `.key` files into the desired directory of the Kong node. + +2) Point [`admin_gui_ssl_cert`] and [`admin_gui_ssl_cert_key`] at the absolute paths of the certificate and key. + +``` +admin_gui_ssl_cert = /path/to/test.crt +admin_gui_ssl_cert_key = /path/to/test.key +``` + +3) Ensure that `admin_gui_url` is prefixed with `https` to use TLS, e.g., + +``` +admin_gui_url = https://test.com:8445 +``` + +### Using https://localhost + +If serving Kong Manager on localhost, it may be preferable to use HTTP as the protocol. If also using RBAC, +set `cookie_secure=false` in `admin_gui_session_conf`. The reason to use HTTP for `localhost` is that +creating TLS certificates for `localhost` requires more effort and configuration, and there may not be any +reason to use it. The adequate use cases for TLS are (1) when data is in transit between hosts, or (2) +when testing an application with [mixed content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) +(which Kong Manager does not use). + +External CAs cannot provide a certificate since no one uniquely owns `localhost`, nor is it rooted in a top-level +domain (e.g., `.com`, `.org`). Likewise, self-signed certificates will not be trusted in modern browsers. Instead, +it is necessary to use a private CA that allows you to issue your own certificates. Also ensure that the SSL state +is cleared from the browser after testing to prevent stale certificates from interfering with future access to +`localhost`. + + +[`admin_gui_auth`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_auth +[`admin_gui_ssl_cert`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_ssl_cert +[`admin_gui_ssl_cert_key`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_ssl_cert_key +[`default_ports`]: /gateway/{{page.release}}/plan-and-deploy/default-ports +[`admin_api_uri`]: /gateway/{{page.release}}/reference/configuration/#admin_api_uri +[`admin_gui_auth_conf`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_auth_conf +[`enforce_rbac`]: /gateway/{{page.release}}/reference/configuration/#enforce_rbac +[`admin_listen`]: /gateway/{{page.release}}/reference/configuration/#admin_listen +[`admin_gui_session_conf`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_session_conf diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/oidc.md b/app/gateway/2.6.x/configure/auth/kong-manager/oidc.md new file mode 100644 index 000000000000..25da08e81bbe --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/oidc.md @@ -0,0 +1,86 @@ +--- +title: Enable OIDC for Kong Manager +badge: enterprise +--- + +{{site.base_gateway}} offers the ability to bind authentication for Kong +Manager **Admins** to an organization's OpenID Connect Identity +Provider using the +**[OpenID Connect Plugin](/hub/kong-inc/openid-connect/)**. + +**Note**: by using the configuration below, it is unnecessary to +manually enable the **Plugin**; the configuration alone will enable +**OIDC** for Kong Manager. + +## Set up RBAC with OIDC + +The following is an example using Google as the IdP and serving Kong Manager +from its default URL, `http://127.0.0.1:8002`. + +(The `admin_gui_auth_config` value must be valid JSON.) + +``` +enforce_rbac = on +admin_gui_auth=openid-connect +admin_gui_session_conf = { "secret":"set-your-string-here" } +admin_gui_auth_conf={ \ + "issuer": "https://accounts.google.com/", \ + "client_id": [""], \ + "client_secret": [""], \ + "consumer_by": ["username","custom_id"], \ + "ssl_verify": false, \ + "consumer_claim": ["email"], \ + "leeway": 60, \ + "redirect_uri": ["http://localhost:8002"], \ + "login_redirect_uri": ["http://localhost:8002"], \ + "logout_methods": ["GET", "DELETE"], \ + "logout_query_arg": "logout", \ + "logout_redirect_uri": ["http://localhost:8002"], \ + "scopes": ["openid","profile","email","offline_access"], \ + "auth_methods": ["authorization_code"] \ +} +``` + +The **Sessions Plugin** requires a secret and is configured securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#session-security), and see [example configurations](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +Replace the entries surrounded by `<>` with values that are valid for your IdP. +For example, Google credentials can be found here: +https://console.cloud.google.com/projectselector/apis/credentials + +## Create an admin + +Create an **Admin** that has a **username** matching the **email** returned from +the Identity Provider upon successful login. + +```bash +$ http POST :8001/admins username="" email="" Kong-Admin-Token: +``` + +For example, if a user has a Google email address, **hal9000@sky.net**: + +```bash +$ http POST :8001/admins username="hal9000@sky.net" email="hal9000@sky.net" Kong-Admin-Token: +``` + +**Note:** The **email** entered for the **Admin** in the request is used to +ensure the **Admin** receives an email invitation, whereas **username** is the +attribute that the **Plugin** uses with the IdP. + +## Assign a role to the admin + +Assign the new **Admin** at least one **Role** so they can log in and access +Kong entities. + +```bash +$ http POST :8001/admins//roles roles="" Kong-Admin-Token: +``` + +For example, if we wanted to grant **hal9000@sky.net** the **Role** of **Super Admin**: + +```bash +$ http POST :8001/admins/hal9000@sky.net/roles roles="super-admin" Kong-Admin-Token: +``` diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/reset-password.md b/app/gateway/2.6.x/configure/auth/kong-manager/reset-password.md new file mode 100644 index 000000000000..17d59c2c8167 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/reset-password.md @@ -0,0 +1,61 @@ +--- +title: Reset Passwords and RBAC Tokens in Kong Manager +badge: enterprise +--- + +## Passwords and RBAC Tokens + +For authentication, Kong uses two different credentials for **Admins**: + +1. An **Admin** uses a **password** to log in to Kong Manager. +2. An **Admin** uses an **RBAC token** to make requests to the Kong Admin API. + +If (and only if) using **Basic Authentication**, an Admin may reset their **password** from within Kong Manager. Since **LDAP** and **OIDC Authentication** imply that an organization stores and manages passwords outside of Kong, password reset is not possible with either type. + +Since a hash of each **RBAC token** is stored in Kong, then regardless of the Authentication option selected, an **Admin** may reset their **RBAC token** from within Kong Manager. Note that to support confidentiality, **RBAC tokens** are hashed and cannot be retrieved after they are created. If a user forgets the token, the only recourse is to reset it. + +## How to Reset a Forgotten Password in Kong Manager + +Prerequisites: + +* `enforce_rbac = on` +* `admin_gui_auth = basic-auth` +* SMTP is configured to send emails + +Steps: + +1. At the login page, click **Forgot Password** beneath the login field. +2. Enter the email address associated with the account. +3. Click the link from the email. +4. Reset the password. Note that you will need to provide it again immediately after the reset is complete. +5. Log in with the new password. + +## How to Reset a Password from within Kong Manager + +Prerequisites: + +* `enforce_rbac = on` +* `admin_gui_auth = basic-auth` +* [`admin_gui_session_conf` is configured](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/). +* Already logged in to Kong Manager + +Steps: + +1. At the **top right corner**, after hovering over the **account name**, select **Profile**. +2. In the **Reset Password** section, fill in the fields and click the **Reset Password** button. + +## How to Reset an RBAC Token in Kong Manager + +Prerequisites: + +* `enforce_rbac = on` +* [`admin_gui_auth` is set](/gateway/{{page.release}}/configure/auth/kong-manager/). +* [`admin_gui_session_conf` is configured](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/). +* Already logged in to Kong Manager + +Steps: + +1. At the **top right corner**, after hovering over the **account name**, select **Profile**. +2. In the **Reset RBAC Token** section at the bottom, click **Reset Token**. +3. Type in a new token and click **Reset**. +4. To copy the token, click the **Copy** button at the right. diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/sessions.md b/app/gateway/2.6.x/configure/auth/kong-manager/sessions.md new file mode 100644 index 000000000000..ca8a128df3aa --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/sessions.md @@ -0,0 +1,104 @@ +--- +title: Sessions in Kong Manager +badge: enterprise +--- + +## How does the Sessions Plugin work in Kong Manager? + +When a user logs in to Kong Manager with their credentials, the Sessions Plugin +will create a session cookie. The cookie is used for all subsequent requests and +is valid to authenticate the user. The session has a limited duration and renews +at a configurable interval, which helps prevent an attacker from obtaining and + using a stale cookie after the session has ended. + +The Session configuration is secure by default, which may +[require alteration](#session-security) if using HTTP or different domains for +the Admin API and Kong Manager. Even if an attacker were to obtain a stale +cookie, it would not benefit them since the cookie is encrypted. The encrypted +session data may be stored either in Kong or the cookie itself. + +## Configuration to Use the Sessions Plugin with Kong Manager + +To enable sessions authentication, configure the following: + +``` +enforce_rbac = on +admin_gui_auth = +admin_gui_session_conf = { + "secret":"", + "cookie_name":"", + "storage":"", + "cookie_lifetime":, + "cookie_renew": + "cookie_secure": + "cookie_samesite":"" +} +``` + +* `"cookie_name":""`: The name of the cookie + * For example, `"cookie_name":"kong_cookie"` +* `"secret":""`: The secret used in keyed HMAC generation. Although + the **Session Plugin's** default is a random string, the `secret` _must_ be + manually set for use with Kong Manager since it must be the same across all + Kong workers/nodes. +* `"storage":""`: Where session data is stored. It is `"cookie"` by default, but may be more secure if set to `"kong"` since access to the database would be required. +* `"cookie_lifetime":`: The duration (in seconds) that the session will remain open; 3600 by default. +* `"cookie_renew":`: The duration (in seconds) of a session remaining at which point + the Plugin renews the session; 600 by default. +* `"cookie_secure":`: `true` by default. See [Session Security](#session-security) for + exceptions. +* `"cookie_samesite":""`: `"Strict"` by default. See [Session Security](#session-security) for + exceptions. + + +{:.important} +> **Important:** The following properties must **not** be altered from default for use with Kong Manager:* +* `logout_methods` +* `logout_query_arg` +* `logout_post_arg` + +For detailed descriptions of each configuration property, learn more in the +[Session Plugin documentation](/hub/kong-inc/session). + +## Session Security + +The Session configuration is secure by default, so the cookie uses the +[Secure, HttpOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies), +and [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies) +directives. + +The following properties must be altered depending on the protocol and domains in use: +* If using HTTP instead of HTTPS: `"cookie_secure": false` +* If using different domains for the Admin API and Kong Manager: `"cookie_samesite": "off"` + +{:.important} +> **Important:** Sessions are not invalidated when a user logs out if `"storage": "cookie"` (the default) is used. In that case, the cookie is deleted client-side. Only when session data is stored server-side with `"storage": "kong"` set is the session actively invalidated. + + +## Example Configurations + +If using HTTPS and hosting Kong Manager and the Admin API from the same domain, +the following configuration could be used for Basic Auth: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { + "cookie_name":"$4m04$" + "secret":"change-this-secret" + "storage":"kong" +} +``` + +In testing, if using HTTP, the following configuration could be used instead: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { + "cookie_name":"04tm34l" + "secret":"change-this-secret" + "storage":"kong" + "cookie_secure":false +} +``` diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/super-admin.md b/app/gateway/2.6.x/configure/auth/kong-manager/super-admin.md new file mode 100644 index 000000000000..14b732a0b3b1 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/super-admin.md @@ -0,0 +1,53 @@ +--- +title: Create a Super Admin +badge: enterprise +--- + +If you seeded a **Super Admin** at the time of running +migrations by passing `KONG_PASSWORD`, you may log in to Kong Manager +with the `kong_admin` username. + +Otherwise, if `enforce_rbac=off`, you may create your first +**Super Admin** within Kong Manager itself. + +You may also use this guide to create additional **Super Admins** once +you have an account and `enforce_rbac=on`. + +1. Go to the "Teams" tab in Kong Manager. + +2. Click "+ Invite Admin" and fill out the form. + +3. Give the user the `super-admin` role in the `default` workspace. + +4. Return to the "Organization" page, and in the "Invited" section, +click the email address of the user in order to view them. + +5. Click "Generate Registration Link". + +6. Copy the link for later use after completing the account setup. + +{:.important} +> **Important:** Kong Manager does not support entity-level RBAC. Run Kong +Manager on a node where `enforce_rbac` is set to `on` or `off`, but not `both`. + + +## How to Create Your First Super Admin Account Post Installation + +In the event that the default `kong_admin`, **Super Admin**, was not seeded +during the initial database preparation step as defined in +[How To Start {{site.base_gateway}} Securely](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/), +the following steps outline how to create and enable a new Super Admin post +installation. + +1. Follow the instructions outlined above to create a new **Super Admin** user +account and generate a registration link. + +2. Before the link generated above can be used, RBAC and GUI Authentication must +be enabled. Follow the instructions on +[how to enable Basic Auth on Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/basic). + +3. Paste the URL in your browser and you will be asked to create a password for +the newly defined **Super Admin** user on the Kong Manager. + +4. Go to the Kong Manager homepage and you will be prompted to login with the +new ***Super Admin*** credentials. diff --git a/app/gateway/2.6.x/configure/auth/kong-manager/workspaces.md b/app/gateway/2.6.x/configure/auth/kong-manager/workspaces.md new file mode 100644 index 000000000000..a8c35cf1b613 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/kong-manager/workspaces.md @@ -0,0 +1,199 @@ +--- +title: Configure Workspaces in Kong Manager +badge: enterprise +--- + +Workspaces enable an organization to segment traffic so that +teams of admins sharing the same Kong cluster are only able to +interact with entities from their groups. Within a workspace, +it is possible to invite admins to a particular team and to +enforce RBAC with roles and permissions that further +delimit the types of actions and entities available to an admin. + +## Prerequisites + +* [`enforce_rbac = on`](/gateway/{{page.release}}/reference/configuration/#enforce_rbac) +* {{site.base_gateway}} has [started](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/) +* Logged in to Kong Manager as a **Super Admin** + +## Default workspace + +When the first Super Admin logs in, they begin in the workspace +named **default**. From here, they may invite admins to manage the default or +any other workspaces. + +## Navigating across workspaces in Kong Manager + +To navigate between workspaces from the **Overview** page, click on any +workspace displayed beneath the **Vitals** chart. + +The list of workspaces may be rendered as cards or a table, +depending on preference. + + +## Create a Workspace + +This guide describes how to create workspaces in Kong +Manager. You can also use the Admin API [`/workspaces/` route](/gateway/{{page.release}}/admin-api/workspaces/reference/#add-workspace) to create a workspace. + +1. Log in as the **Super Admin**. On the **Workspaces** page, click the **New Workspace** +button at the top right to see the **Create Workspace** form. Name and choose a +color / icon for the new Workspace. + + Each workspace name should be unique, + regardless of letter case. For example, naming one + workspace "Payments" and another one "payments" will + create two different workspaces that appear identical. + + Do not name workspaces the same as these major API names (paths) + in Admin API: + + ``` + • Admins + • Certificates + • Consumers + • Plugins + • Portal + • Routes + • Services + • SNIs + • Upstreams + • Vitals + ``` + +2. Click the **Create New Workspace** button. Upon creation, the application will +navigate to the new Workspace's dashboard. + + +## Edit a workspace + +1. In the workspace you want to edit, navigate to the **Dashboard** page. + +1. Near the top right, click the **Settings** button. This button takes you to the **Edit Workspace** page. + +1. Here, you can edit the workspace avatar and avatar background color. + +1. Click **Update Workspace** to save. + +## Delete a workspace + +### Wipe workspace data +To delete a workspace, *all data* must first be deleted from the workspace. +Choose one of the following methods. + +{% navtabs %} +{% navtab Kong Manager %} +Using Kong Manager, complete the following: + +1. Manually delete all files via **Dev Portal** > **Editor**. You cannot delete folders at this time, but deleting +all files from a folder will remove the folder. +1. Turn off the Dev Portal. Go to Dev Portal **Settings** > **Advanced** > **Turn Off**. +1. Remove all roles from the workspace: + 1. Go to **Teams** in the top navigation. + 1. Navigate to the **Roles** tab. + 1. Click **View** on the workspace you want to delete. + 1. Go to each role entry and click **Edit**. + 1. In the entry detail page, click **Delete Role**. A confirmation modal will appear. Click **Delete Role** again. + +{% endnavtab %} +{% navtab Admin API %} + +1. Delete all Dev Portal files associated with the workspace: + + ```bash + curl -i -X DELETE http://localhost:8001/{WORKSPACE_NAME}/files + ``` + +1. Turn off the Dev Portal for the workspace: + + ```bash + curl -X PATCH http://localhost:8001/workspaces/{WORKSPACE_NAME} \ + --data "config.portal=false" + ``` + +1. [Delete each role](/gateway/{{page.release}}/admin-api/rbac/reference/#delete-a-role) +from the workspace: + + ```bash + curl -i -X DELETE http://localhost:8001/{WORKSPACE_NAME}/rbac/roles/{ROLE_NAME|ROLE_ID} + ``` +{% endnavtab %} +{% navtab Portal CLI %} + +1. Delete all Dev Portal files associated with the workspace: + + ```sh + portal wipe WORKSPACE_NAME + ``` + +2. Turn off the Dev Portal for the workspace: + + ```sh + portal disable WORKSPACE_NAME + ``` + +3. Delete each role from the workspace. You can't complete this step using the +Portal CLI, so switch to either the *Kong Manager* or *Admin API* tab and complete +step 3. + +{% endnavtab %} +{% endnavtabs %} + +### Delete a clean workspace + +If your workspace is clean, you can delete it using the Kong Manager GUI or the +Kong Admin API. If not, see the previous section to [wipe workspace data](#wipe-workspace-data). + +{% navtabs %} +{% navtab Kong Manager %} + +1. In the workspace you want to delete, navigate to the **Dashboard** page. + +1. Near the top right, click the **Settings** button. This button takes you to the **Edit Workspace** page. + +1. Click **Delete** in the bottom right corner. + + The deletion will fail if you have any data in your workspace. + +{% endnavtab %} +{% navtab Admin API %} + +Send a `DELETE` request to the Kong Admin API: + +```sh +curl -i -X DELETE http://localhost/workspaces/{WORKSPACE_NAME|WORKSPACE_ID} +``` + +The deletion will fail if you have any data in your workspace. + +If it is successful, you should see the following response: + +``` +HTTP 204 No Content +``` + +{% endnavtab %} +{% endnavtabs %} + +## Workspace Access + +If a role does not have permission to access entire endpoints within +a workspace, the admin assigned to that role will not be +able to see the related navigation links. + +To set up access: +1. Open Kong Manager. +2. On the left sidebar, click the **Admins** link in the +**Security** section. + + If the sidebar is collapsed, hover over + the **security badge icon** at the bottom and click the + **Admins** link. + +The Admins page displays a list of current admins and +roles. Four default roles specific to the new +workspace are already visible, and new roles specific +to the workspace can be assigned from this page. + +For more information about admins and roles, see +[RBAC in Kong Manager](/gateway/{{page.release}}/configure/auth/rbac/). diff --git a/app/gateway/2.6.x/configure/auth/oidc-auth0.md b/app/gateway/2.6.x/configure/auth/oidc-auth0.md new file mode 100644 index 000000000000..02174544d07c --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/oidc-auth0.md @@ -0,0 +1,49 @@ +--- +title: OpenID Connect with Auth0 +badge: enterprise +--- + +This guide covers an example OpenID Connect plugin configuration to authenticate headless service consumers using Auth0's identity provider. + +## Auth0 IDP Configuration + +This configuration will use a [client credentials grant][client-credentials-grant] as it is non-interactive, and because we expect clients to authenticate on behalf of themselves, not an end-user. To do so, you will need to [create an Auth0 API][create-auth0-api] and a [non-interactive client][non-interactive-client]. + +### API Configuration + +When creating your API, you will need to specify an Identifier. Using the URL that your consumer makes requests to is generally appropriate, so this will typically be the hostname/path combination configured as an API in Kong. + +After creating your API, you will also need to add the `openid` scope at `https://manage.auth0.com/#/apis//scopes`. + +### Client Configuration + +You will need to authorize your client to access your API. Auth0 will prompt you to do so after client creation if you select the API you created previously from the client's Quick Start menu. After toggling the client to Authorized, expand its authorization settings and enable the `openid` scope. + +## Kong Configuration + +If you have not done so already, [create a **Service**][add-service] to protect. The `url` configuration should match the Identifier you used when configuring Auth0. + +Add an OpenID plugin configuration using the parameters in the example below using an HTTP client or Kong Manager. Auth0's token endpoint [requires passing the API identifier in the `audience` parameter][audience-required], which must be added as a custom argument: + +```bash +curl -i -X POST http://localhost:8001/kong-admin/services/{SERVICE_NAME}/plugins \ + --data name="openid-connect" \ + --data config.auth_methods="client_credentials" \ + --data config.issuer="https://.auth0.com/.well-known/openid-configuration" \ + --data config.token_post_args_names="audience" \ + --data config.token_post_args_values="https://example.com/" +``` + +## Downstream configuration + +The service accessing your resource will need to pass its credentials to Kong. It can do so via HTTP basic authentication, query string arguments, or parameters in the request body. Basic authentication is generally preferable, as credentials in a query string will be present in Kong's access logs (and possibly in other infrastructure's access logs, if you have HTTP-aware infrastructure in front of Kong) and credentials in request bodies are limited to request methods that expect +client payloads. + +For basic authentication, use your client ID as the username and your client secret as the password. For the other methods, pass them as parameters named `client_id` and `client_secret`, respectively. + + +[client-credentials-grant]: https://auth0.com/docs/api-auth/tutorials/client-credentials +[create-auth0-api]: https://auth0.com/docs/apis#how-to-configure-an-api-in-auth0 +[non-interactive-client]: https://auth0.com/docs/clients +[add-service]: /gateway/{{page.release}}/admin-api/#service-object +[audience-required]: https://auth0.com/docs/api/authentication#client-credentials diff --git a/app/gateway/2.6.x/configure/auth/oidc-azuread.md b/app/gateway/2.6.x/configure/auth/oidc-azuread.md new file mode 100644 index 000000000000..5acb2da6aef0 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/oidc-azuread.md @@ -0,0 +1,133 @@ +--- +title: OpenID Connect with Azure AD +badge: enterprise +--- + +This guide covers an example OpenID Connect plugin configuration to authenticate +browser clients using an Azure AD identity provider. + +For information about configuring OIDC using Azure as an Identity provider +in conjunction with the Application Registration plugin, see +[Set Up External Portal Application Authentication with Azure AD and OIDC](/gateway/{{page.release}}/developer-portal/administration/application-registration/azure-oidc-config). + +## Prerequisites + +Because OpenID Connect deals with user credentials, all transactions should take place over HTTPS. +Although user passwords for third party identity providers are only submitted to +those providers and not Kong, authentication tokens do grant access to a subset of +user account data and protected APIs, and should be secured. As such, you should +make Kong's proxy available via a fully-qualified domain name and [add a certificate][add-certificate] for it. + +## Kong Configuration + +If you have not yet [added a **Route** and a **Service**][add-service], go ahead +and do so. Again, note that you should be able to secure this route with HTTPS, +so use a hostname you have a certificate for. Add a location handled by your +Route as an authorized redirect URI in Azure (under the **Authentication** section of your app registration). + +## Azure AD IdP Configuration + +You must [register an app][azure-create-app] in your Azure AD configuration and [add a client secret credential][azure-client-secret] that Kong will use to access it. You must also configure a redirect URI that is handled by your Route. + +Azure AD provides two interfaces for its OAuth2/OIDC-related endpoints: v1.0 and v2.0. +Support for some legacy v1.0 behavior is still available on v2.0, including use of v1.0 tokens by +default, which is not compatible with Kong's OIDC implementation. To force Azure AD to use v2.0 tokens, +[edit your application manifest][azure-manifest] and set `accessTokenAcceptedVersion` to `2` and +include a `YOUR_CLIENT_ID/.default` scope in your plugin configuration as shown below. + +## Plugin Configuration + +Add a plugin with the configuration below to your Route using an HTTP client or [Kong Manager][enable-plugin]. + +```bash +$ curl -i -X POST https://admin.kong.example/routes/ROUTE_ID/plugins --data name="openid-connect" \ + --data config.issuer="https://login.microsoftonline.com/YOUR_DIRECTORY_ID/v2.0/.well-known/openid-configuration" \ + --data config.client_id="YOUR_CLIENT_ID" \ + --data config.client_secret="YOUR_CLIENT_SECRET" \ + --data config.redirect_uri="https://example.com/api" \ + --data config.scopes="openid" \ + --data config.scopes="email" \ + --data config.scopes="profile" \ + --data config.scopes="YOUR_CLIENT_ID/.default" \ + --data config.verify_parameters="false" +``` + +Some of the configurations above must use values specific to your environment: + +* The `issuer` URL can be retrieved by clicking the **Endpoints** button on your app registration's **Overview** page. +* `redirect_uri` should be the URI you specified earlier when configuring your app. You can +add one via the **Authentication** section of the app settings if you did not add one initially. +* For `client_id` and `scopes`, replace `YOUR_CLIENT_ID` with the client ID shown on the app **Overview** page. +* For `client_secret`, replace `YOUR_CLIENT_SECRET` with the URL-encoded representation of the +secret you created earlier in the **Certificates & secrets** section. Azure AD secrets +often include reserved URL characters, which cURL might handle incorrectly if they are not URL-encoded. + +Visiting a URL matched by that route in a browser will now redirect to Microsoft's +authentication site and return you to the redirect URI after authenticating. + +### Access Restrictions + +The configuration above allows users to authenticate and access the Route even though no +Consumer was created for them: any user with a valid account in the directory +will have access to the Route. The OIDC plugin allows this as the simplest +authentication option, but you might want to restrict access further. There are several options for this: + +- Domain Restrictions +- Consumer Mapping +- Pseudo-Consumer Mapping + +#### Domain Restrictions + +Azure AD does not provide identity tokens with the `hd` claim, and as such, the +OIDC plugin's `domains` configuration cannot restrict users based on their domain. +Using a [single-tenant][azure-tenant] application will restrict access to users +in your directory only. Multi-tenant apps allow users with Microsoft accounts +from other directories and optionally any Microsoft account (e.g., live.com or Xbox accounts) to sign in. + +#### Consumer Mapping + +If you need to interact with other Kong plugins using Consumer information, you can +add configuration that maps account data received from the identity provider to a Kong Consumer. +For this example, the user's Azure AD account GUID is mapped to a Consumer by setting +it as the `custom_id` on their Consumer: + +```bash +$ curl -i -X POST http://admin.kong.example/consumers/ \ + --data username="Yoda" \ + --data custom_id="e5634b31-d67f-4661-a6fb-b6cb77849bcf" + +$ curl -i -X PATCH http://admin.kong.example/plugins/OIDC_PLUGIN_ID \ + --data config.consumer_by="custom_id" \ + --data config.consumer_claim="oid" +``` + +Now, if a user logs into an Azure AD account with the GUID `e5634b31-d67f-4661-a6fb-b6cb77849bcf`, +Kong will apply configuration associated with the Consumer `Yoda` to their requests. + +This also requires that clients login using an account mapped to some Consumer, +which may not be desirable (e.g., you apply OpenID Connect to a Service, but only +use plugins requiring a Consumer on some routes). To deal with this, you can set +the `anonymous` parameter in your OIDC plugin configuration to the ID of a generic +Consumer, which will then be used for all authenticated users that cannot be mapped +to some other Consumer. You can alternately set `consumer_optional` to `true` to allow +similar logins without mapping an anonymous Consumer. + +#### Pseudo-Consumer Mapping + +For plugins that typically require Consumers, the OIDC plugin can provide a consumer ID +based on the value of a claim without mapping to an actual Consumer. Setting `credential_claim` +to a claim [in your plugin configuration][credential-claim] will extract the value +of that claim and use it where Kong would normally use a consumer ID. Note that this +may not work with all consumer-related functionality. + +Similarly, setting `authenticated_groups_claim` will extract that claim's value and use it as a group for the ACL plugin. + +[azure-client-secret]: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application +[azure-create-app]: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app +[azure-manifest]: https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-app-manifest#configure-the-app-manifest +[azure-tenant]: https://docs.microsoft.com/en-us/azure/active-directory/develop/single-and-multi-tenant-apps +[add-certificate]: /gateway/{{page.release}}/admin-api/#add-certificate +[add-service]: /gateway/{{page.release}}/admin-api/#service-object +[oidc-id-token]: http://openid.net/specs/openid-connect-core-1_0.html#IDToken +[credential-claim]: /hub/kong-inc/openid-connect/#configcredential_claim +[enable-plugin]: /gateway/{{page.release}}/admin-api/#plugin-object diff --git a/app/gateway/2.6.x/configure/auth/oidc-cognito.md b/app/gateway/2.6.x/configure/auth/oidc-cognito.md new file mode 100644 index 000000000000..52cdf21bd990 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/oidc-cognito.md @@ -0,0 +1,194 @@ +--- +title: OpenID Connect with Amazon Cognito +badge: enterprise +--- + +## Amazon Cognito Configuration + +Amazon Cognito has two significant components: Identity Pools and User Pools. Identity Pools are the original functionality deployed in 2014; they mainly use proprietary AWS interfaces and libraries to accomplish the task of authenticating users. Furthermore, Identity Pools have no concept of claims (standard or custom) stored in the system; it is entirely a federated identity construct. User Pools are the more recent addition to the Cognito feature set; User Pools are a multi-tenant LDAP-like user repository combined with an OAuth2 and an OpenID Connect interface. + +In this configuration, we use User Pools. + +1. Log in to AWS Console. +1. Navigate to the Amazon Cognito Service. + +1. Click on **Manage User Pools**. + +1. Click the **Create a user pool** button on the right-hand side. + +1. Enter a pool name; we use “test-pool” for this example. + +1. Click **Step Through Settings**. + +1. Select **Email address or phone number**, and under that, select **Allow email addresses**. Select the following standard attributes as required: email, family name, given name. + +1. Click **Next step**. +1. Accept the defaults for **Password settings**, then click **Next step**. +1. Accept the defaults for **MFA and verifications**, then click **Next step**. +1. Accept the defaults for **Message customizations**, click **Next step**. +1. On the next screen, we are not going to create any tags. Click **Next step**. +1. Select **No** for **Do you want to remember your user’s devices**, then click **Next step**. +1. We can create an application definition later. Keep things simple for now and click **Next step**. +1. We don’t have any need for Triggers or customized Sign Up/Sign In behavior for this example. Scroll down and click **Save Changes**. + +1. Click **Create pool**. Wait a moment for the success message. +1. Make a note of the **Pool ID**. You will need this when configuring the application later. + +## Application Definition + +You need to add an OAuth2 application definition to the User Pool we just created. + +1. Go to the App clients screen in the AWS Cognito management screen for the User Pool we just created. + +1. Click “Add an app client”. + +1. Enter an App client name. This demo is using “kong-api”. + +1. Enter a Refresh token expiration (in days). We will use the default of 30 days. +1. Do not select “Generate client secret”. This example will use a public client. + +1. Do not select any other checkboxes. + +1. Click the “Set attribute read and write permissions” button. + +1. Let’s make this simple and only give the user read and write access to the required attributes. So, uncheck everything except the email, given name, and family name fields. + +1. Click “Create app client”. + +1. Click “Show Details”. + +1. Take note of the App client ID. We will need that later. +1. Go to the App integration -> App client settings screen. +1. Click the “Cognito User Pool” checkbox under Enabled Identity Providers. +1. Add the following to the Callback URLs field: + + ``` + “https://kong-ee:8446/default, https://kong-ee:8447/default/, https://kong-ee:8447/default/auth, https://kong-ee:8443/cognito” + ``` + + Note that AWS Cognito doesn’t support HTTP callback URLs. This field should + include the API and Dev Portal URLs that you want to secure using AWS Cognito. + +1. Click the “Authorization code grant” checkbox under Allowed OAuth Flows. +1. Click the checkboxes next to email, OpenID, aws.cognito.signin.user.admin, and profile. +1. Click the “Save changes” button. +1. Click on the domain name tab. +1. Add a sub-domain name. +1. Click the Check Availability button. +1. As long as it reports “This domain is available”, the name you have chosen will work. +1. Click the “Save changes” button. + +Now that you have created an Amazon Cognito User Pool and Application Definition, we can configure the OpenID Connect plugin in Kong. We can then test integration between Dev Portal and Amazon Cognito. + +Amazon’s OIDC discovery endpoint is available from: +``` +https://cognito-idp..amazonaws.com/ +``` + +For example, in this demo, the OIDC discovery endpoint is: + +``` +https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_ie577myCv/.well-known/openid-configuration +``` + +The OAuth + OIDC debugger is a handy utility that you may use to test the authorization flow before configurations in Kong. + +## OIDC Plugin Configuration + +Identify the Route or Service to be secured. In our example, we created a new route called /cognito to which we added the OpenID Connect plug-in. +The number of options in the plug-in can seem overwhelming but the configuration is rather simple. All you need to do is configure: +* `issuer` - You can use the OIDC discovery endpoint here, e.g. + ``` + https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_ie577myCv/.well-known/openid-configuration + ``` +* `config.client_id` - This is the client ID noted when the application was created +* `config.client_secret` - This is the client secret noted when the application was created. In this demo we are leaving this blank as we didn’t create a client secret. +* `config.auth_methods` - If this is left blank, all flows will be enabled. If only specific flows are in scope, configure the appropriate flows accordingly. + +## Validating the Flows + +You can test the route by accessing URL “https://kong-ee:8443/cognito/anything”, and you should redirect to the Amazon Cognito login page. You need to click “Sign up” link to create a user first using your email address. The application sends a verification code to your email. Once you enter the verification code, Amazon Cognito acknowledges the account. + +You can verify the confirmed user from the Cognito page under “General settings” -> “Users and groups”. + +## Dev Portal Integration + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + +Since AWS Cognito only supports the HTTPS protocol, when you start {{site.base_gateway}}, ensure that HTTPS protocol for Dev Portal is enabled. For example: + +``` +docker run -d --name kong-ee --link kong-ee-database:kong-ee-database \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_CASSANDRA_CONTACT_POINTS=kong-ee-database" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001 , 0.0.0.0:8444 ssl" \ + -e "KONG_PORTAL=on" \ + -e "KONG_ENFORCE_RBAC=off" \ + -e "KONG_ADMIN_GUI_URL=http://kong-ee:8002" \ + -e "KONG_AUDIT_LOG=on" \ + -e "KONG_PORTAL_GUI_PROTOCOL=https" \ + -e "KONG_PORTAL_GUI_HOST=kong-ee:8446" \ + -e "KONG_LICENSE_DATA=$KONG_LICENSE_DATA" \ + -p 8000-8004:8000-8004 \ + -p 8443-8447:8443-8447 \ + kong-ee +``` + +Under Dev Portal settings, select “Open ID Connect” as the authentication plugin. + +Copy and paste the following Auth Config JSON object: + +``` +{ + "leeway": 100, + "consumer_by": [ + "username", + "custom_id", + "id" + ], + "scopes": [ + "openid", + "profile", + "email" + ], + "logout_query_arg": "logout", + "client_id": [ + "1pf00c5or942c2hm37mgv0u509" + ], + "login_action": "redirect", + "logout_redirect_uri": [ + "https://kongdemo.auth.ap-southeast-1.amazoncognito.com/logout?client_id=1pf00c5or942c2hm37mgv0u509&logout_uri=kong-ee:8446/default" + ], + "login_tokens": {}, + "login_redirect_uri": [ + "https://kong-ee:8446/default" + ], + "forbidden_redirect_uri": [ + "https://kong-ee:8446/default/unauthorized" + ], + "ssl_verify": false, + "issuer": "https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_ie577myCv/.well-known/openid-configuration", + "logout_methods": [ + "GET" + ], + "consumer_claim": [ + "email" + ], + "login_redirect_mode": "query", + "redirect_uri": [ + "https://kong-ee:8447/default/auth" + ] +} +``` + +To log out the user completely, we need to use the logout endpoint provided by Cognito (https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html). Therefore, in the above configuration, we have passed in Cognito logout endpoint of logout redirect URL. + +Please also note that the developer signed up from Dev Portal doesn’t get created in Cognito automatically. Therefore, developer sign-up is a two-step process: +* The developer signs up from Dev Portal itself, so a Kong Admin needs to approve the developer access. +* The developer signs up from Amazon Cognito. Please make sure that you use the _same email address_ for both sign-ups. +Now you should be able to login to Developer Portal using the Amazon Cognito user and credential. diff --git a/app/gateway/2.6.x/configure/auth/oidc-curity.md b/app/gateway/2.6.x/configure/auth/oidc-curity.md new file mode 100644 index 000000000000..99d50d2c677d --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/oidc-curity.md @@ -0,0 +1,209 @@ +--- +title: OpenID Connect with Curity +badge: enterprise +--- + +## Phantom Token Integration + +This guide describes how to integrate {{site.ee_product_name}} and the Curity Identity Server using the Kong [OpenID Connect](/hub/kong-inc/openid-connect/) plugin. + +This guide focuses on configuring the plugin for introspection, and especially as it relates to the introspection using the [Phantom Token pattern][curity-phantom-token-pattern]. Some tweaks are made so that a phantom token is provided in the introspection response and then passed on to the upstream API. + +Configuring the Curity Identity Server to provide a Phantom Token in the introspection response is outlined in more detail in this [Introspection and Phantom Tokens][curity-phantom-token-introspection] article. + +### Prerequisites + +* An installation of the [Curity Identity Server][curity-getting-started] +* An introspection endpoint configured with the [Token Procedure Approach][curity-phantom-token-introspection] + +### Configure Kong + +The Kong OpenID Connect plugin is configured to introspect an incoming opaque access token and in return receive a JWT in the introspection response from the Curity Identity Server. The plugin is enabled for a [service or a route][kong-add-service]. + +As part of the introspection, the OpenID Connect plugin also has the ability to validate that required scopes are available in the introspected token. Access to the requested API are denied if the correct scopes are missing. + +If access is granted, the JWT from the introspection response is added to a header and forwarded to the upstream API where it can be consumed. + +#### Create a service + +Create a service that can be used to test the integration. + +```bash +curl -i -X POST http://localhost:8001/services/ \ + --data name="httpbin" \ + --data protocol="http" \ + --data url="https://httpbin.konghq.com" +``` + +#### Create a route + +Add a route to the service. + +```bash +curl -i -X POST http://localhost:8001/services/httpbin/routes \ + --data "paths[]=/httpbin" +``` + +#### Configure the plugin + +The Kong OpenID Connect plugin is enabled for the previously created service. In the example below, the `openid` scope is required in order for access to be granted. As noted by the `config.upstream_headers_claims` configuration, the plugin looks for the `JWT` (the phantom token) claim in the introspection response. The `config.upstream_headers_names` configuration extracts the `JWT` from the introspection response and adds it to a `phantom_token` header in the call to the upstream API. + +```bash +curl -X POST http://localhost:8001/services/httpbin/plugins \ +--data name="openid-connect" \ +--data config.issuer="https://idsvr.example.com/oauth/v2/oauth-anonymous" \ +--data config.client_id="gateway-client" \ +--data config.client_secret="Password1" \ +--data config.scopes_required="openid" \ +--data config.hide_credentials="true" \ +--data config.upstream_access_token_header= \ +--data config.upstream_headers_claims="phantom_token" \ +--data config.upstream_headers_names="phantom_token" \ +--data config.auth_methods="introspection" +``` + +Parameter | Description | Example | Required for integration +--- |--- |--- |--- +`config.issuer` | Used for discovery. Kong appends `/.well-known/openid-configuration`. Should be set to the `realm` or `iss` if no discovery endpoint is available. | `https://idsvr.example.com/oauth/v2/oauth-anonymous` | Yes +`config.client_id` | The ID of a client with the introspection capability | `gateway-client`| Yes +`config.client_secret` | Secret of the client used for introspection| `Password1` | Yes +`config.scopes_required`| Optional scopes required in introspection result for coarse grained authorization. By default the plugin looks for the scopes in the `scopes` claim in the introspection result. This could be overridden with the `config.scopes_claim` configuration. | `openid email records_read` | No +`config.hide_credentials` | Boolean value. This will prevent the incoming Access Token from being forwarded to the upstream API. |`true` | No +`config.upstream_access_token_header` | In order to prevent the plugin from adding the Access Token back in the upstream request, actively set this value to nothing (aka, `nil`) by setting `config.upstream_access_token_header=` as in the example above . This configuration works in conjunction with `config.hide_credentials` to prevent the incoming Access Token from being passed to the upstream API. | `authorization:bearer` | No +`config.upstream_headers_claims` | Contains claim that holds Phantom Token in the introspection result. | `phantom_token` | Yes +`config.upstream_headers_names` | Contains upstream header name that will hold the Phantom Token from the introspection result. | `phantom_token` | Yes +`config.auth_methods` | Several methods are supported for authenticating the request. For this use case, this should be limited to `introspection`. |`introspection` | No +`config.cache_introspection` | Boolean value that controls whether an introspection result should be cached. | `true` | No +`config.introspect_jwt_tokens` | Boolean value that controls if JWTs sent in an Authorization header should also be introspected. | `false` | No +`config.introspection_endpoint` | Endpoint for introspection. Might be needed if discovery is not possible. | `https://idsvr.example.com/oauth/v2/oauth-introspect` | No + +### Test the configuration + +Any supported OAuth/OIDC flow can be used to obtain an opaque access token from the Curity Identity Server. Several approaches for obtaining a token are outlined in the [Curity Getting Started Guide][curity-getting-started]. Make sure that the token issued contains the `openid` scope. + +Call the exposed service created earlier and pass the opaque access token in the `Authorization` header. + +```bash +curl -X GET http://kong:8000/httpbin/get \ +--header "Authorization: Bearer /auth`). + +{:.note} +> **NOTE:** There is an issue with short-lived access tokens that is under investigation. Increase the `Access Token Time to Live` in the client configuration to `3000` as a temporary workaround. + +More information is available in the [Code Flow][curity-code-flow-tutorial] tutorial. + +### Configure OpenID Connect in the Kong Developer Portal + +Enabling the Kong Developer Portal is outlined in the [Kong Dev Portal Documentation][kong-dev-portal-doc] and not covered in this article. The documentation also covers how to configure the [OpenID Connect Plugin][kong-dev-portal-doc-oidc]. + +#### Example Configuration Object + +Below is an example configuration object that is used to configure the OIDC plugin for the Dev Portal. + +```json +{ + "redirect_uri": ["https://kong-dev-portal:8004/default/auth"], + "consumer_by": ["username","custom_id","id"], + "leeway": 1000, + "scopes": ["openid","profile","email"], + "logout_query_arg": "logout", + "login_redirect_uri": ["https://kong-dev-portal:8003"], + "login_action": "redirect", + "logout_redirect_uri": ["https://kong-dev-portal:8003"], + "ssl_verify": false, + "client_id": ["kong-dev-portal-client"], + "forbidden_redirect_uri": ["https://kong-dev-portal:8003/unauthorized"], + "client_secret": ["Pa$$w0rd!"], + "issuer": "https://idsvr.example.com/oauth/v2/oauth-anonymous/", + "logout_methods": ["GET"], + "consumer_claim": ["email"], + "login_redirect_mode": "query" +} +``` + +### Curity Authentication Action + +An Authentication Action to automatically provision the user to the Kong Developer Portal is available in the Curity GitHub repository. Using the Action is not mandatory as the user could be provisioned in other ways, such as manually through the Kong Developer portal login page. However, using the Authentication Action would streamline the user flow since the Action takes the user's full name and the email from the Curity Authenticator and automatically provision that to the Kong Developer Portal using the exposed API. + +The [Kong Developer Portal User Provisioner][curity-kong-dev-portal-user-provisioner] action is available as open source and can be forked to fit the needs of the environment as needed. + +#### Configuration + +This Action is straightforward to configure. An HTTP Client is needed to communicate with the Kong Dev Portal API. By default, the **HTTP Authentication** can be left out. Only a correct scheme needs to be configured (HTTP or HTTPS). + +The Action also configures the URL to the registration endpoint of the Kong Developer Portal. Here the scheme needs to match what's configured in the HTTP Client used. + +When the action is created, it can be assigned to the Authenticators used in the client configured in the Curity Identity Server as described above. + +#### Action to Resolve Additional User Information + +Depending on the Authenticator used, an additional Action may be needed to resolve additional information. By default, The Kong Developer portal provisioning requires `Full Name` and `email`. If the Authenticator does not provide this, it's possible to use an Action to resolve the data. This could be as simple as a **Data Source** action configured to use a Data Source that provides the information. + +![Chain Actions](/assets/images/products/gateway/dev-portal/authentication-and-actions.png) + +By default, the Kong Developer Portal Provisioner Action works on the default account table schema of the Curity Identity Server database. This provides `email` as a column, but the `Full Name` is not readily available. The Action operates on the `attributes` column and parse the information to pass the user's Full Name to the Kong Dev Portal. + +The attributes column contains this structure: + +```json +{"emails":[{"value":"alice@example.com","primary":true}],"phoneNumbers":[{"value":"555-123-1234","primary":true}],"name":{"givenName":"alice","familyName":"anderson"},"agreeToTerms":"on","urn:se:curity:scim:2.0:Devices":[]} +``` + +The data source used to resolve additional information needs to be configured with an appropriate **Attribute Query**. This would look similar to this: + +```sql +select * from "accounts" where "username"= :subject +``` + +### Conclusion + +With relatively simple configurations in both the Curity Identity Server and the Kong Developer Portal, it's possible to leverage Curity as the Identity Provider for the Kong Dev Portal. This provides a very seamless flow for user authentication to the Kong Dev Portal. With the added capability of an Authentication Action, it is possible to automatically provision the user to the Kong Dev Portal for an even more streamlined experience. + +[kong-add-service]: /gateway/{{page.release}}/admin-api/#service-object +[curity-phantom-token-introspection]: https://curity.io/resources/learn/introspect-with-phantom-token +[curity-getting-started]: https://curity.io/resources/getting-started +[curity-phantom-token-pattern]: https://curity.io/resources/learn/phantom-token-pattern +[curity-code-flow-tutorial]: https://curity.io/resources/learn/code-flow +[curity-kong-dev-portal-user-provisioner]: https://curity.io/resources/learn/provision-kong-dev-portal-user +[kong-dev-portal-doc]: /gateway/{{page.release}}/developer-portal +[kong-dev-portal-doc-oidc]: /gateway/{{page.release}}/developer-portal/configuration/authentication/oidc diff --git a/app/gateway/2.6.x/configure/auth/oidc-google.md b/app/gateway/2.6.x/configure/auth/oidc-google.md new file mode 100644 index 000000000000..da98b123772d --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/oidc-google.md @@ -0,0 +1,67 @@ +--- +title: OpenID Connect with Google +badge: enterprise +--- + +This guide covers an example OpenID Connect plugin configuration to authenticate browser clients using Google's identity provider. + +## Prerequisites + +Because OpenID Connect deals with user credentials, all transactions should take place over HTTPS. Although user passwords for third party identity providers are only submitted to those providers and not Kong, authentication tokens do grant access to a subset of user account data and protected APIs, and should be secured. As such, you should make Kong's proxy available via a fully-qualified domain name and [add a certificate][add-certificate] for it. + +## Google IDP Configuration + +Before configuring Kong, you'll need to set up a Google APIs project and create a credential set. Following [Google's instructions][google-oidc], [create a new set of OAuth client ID credentials][google-create-credentials] with the Web application class. Add an authorized redirect URI for part of the API you wish to protect (more complex applications may redirect to a resource that sets additional +application-specific state on the client, but for our purposes, any protected URI will work). Authorized JavaScript origins can be left blank. + +You can optionally customize the consent screen to inform clients who/what application is requesting authentication, but this is not required for testing. All steps after can be ignored, as Kong handles the server-side authentication request and token validation. + +## Kong Configuration + +If you have not yet [added a **Service**][add-service], go ahead and do so. Again, note that you should be able to secure this Service with HTTPS, so if you are configuring a host, use a hostname you have a certificate for. + +### Basic Plugin Configuration + +Add a plugin with the configuration below to your Service using an HTTP client or Kong Manager. Make sure to use the same redirect URI as configured earlier: + +```bash +curl -i -X POST http://localhost:8001/services/{SERVICE_NAME}/plugins \ + --data name="openid-connect" \ + --data config.issuer="https://accounts.google.com/.well-known/openid-configuration" \ + --data config.client_id="YOUR_CLIENT_ID" \ + --data config.client_secret="YOUR_CLIENT_SECRET" \ + --data config.redirect_uri="https://example.com/api" \ + --data config.scopes="openid,email" +``` + +Visiting a URL matched by that Service in a browser will now redirect to Google's authentication site and return you to the redirect URI after authenticating. You'll note, however, that we did not configure anything to map authentication to consumers and that no consumer is associated with the subsequent request. Indeed, if you have configured other plugins that rely on consumer information, such as the ACL plugin, you will not have access. At present, the plugin configuration confirms that +users have a Google account, but doesn't do anything with that information. + +Depending on your needs, it may not be necessary to associate clients with a consumer. You can, for example, configure the `domains` parameter to limit access to a internal users if you have a G Suite hosted domain, or configure `upstream_headers_claims` to send information about the user upstream (e.g. their email, a profile picture, their name, etc.) for use in your applications or for analytics. + +### Consumer Mapping + +If you need to interact with other Kong plugins using consumer information, you must add configuration that maps account data received from the identity provider to a Kong consumer. For this example, we'll map the user's Google account email by setting a `custom_id` on their consumer, e.g. + +```bash +curl -i -X POST http://localhost:8001/consumers/ \ + --data username="Yoda" \ + --data custom_id="user@example.com" + +curl -i -X PATCH http://localhost:8001/services/{SERVICE_NAME}/plugins/{OIDC_PLUGIN_ID} \ + --data config.consumer_by="custom_id" \ + --data config.consumer_claim="email" +``` + +Now, if a user logs into a Google account with the email `user@example.com`, Kong will apply configuration associated with the consumer `Yoda` to their requests. Note that while Google provides account emails, not all identity providers will. OpenID Connect does not have many required claims--the [only required user identity claim][oidc-id-token] is `sub`, a unique subscriber ID. Many optional claims [are +standardized][oidc-standard-claims], however--if a provider returns an `email` claim, the contents will always be an email address. + +This also requires that clients login using an account mapped to some consumer, which may not be desirable (e.g. you apply OpenID Connect to a service, but only use plugins requiring a consumer on some routes). To deal with this, you can set the `anonymous` parameter in your OIDC plugin configuration to the ID of a generic consumer, which will then be used for all authenticated users that cannot be mapped to some other consumer. + + +[add-certificate]: /gateway/{{page.release}}/admin-api/#add-certificate +[google-oidc]: https://developers.google.com/identity/protocols/OpenIDConnect +[google-create-credentials]: https://console.developers.google.com/apis/credentials +[add-service]: /gateway/{{page.release}}/admin-api/#service-object +[oidc-id-token]: http://openid.net/specs/openid-connect-core-1_0.html#IDToken +[oidc-standard-claims]: http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims diff --git a/app/gateway/2.6.x/configure/auth/oidc-mapping.md b/app/gateway/2.6.x/configure/auth/oidc-mapping.md new file mode 100644 index 000000000000..d715bafbfe9e --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/oidc-mapping.md @@ -0,0 +1,257 @@ +--- +title: OIDC Authenticated Group Mapping +badge: enterprise +--- + +Using Kong's OpenID Connect plugin (OIDC), you can map identity provider (IdP) +groups to Kong roles. Adding a user to Kong in this way gives them access to +Kong based on their group in the IdP. + +After starting {{site.base_gateway}} with the desired configuration, you can +create new admins whose usernames match those in your IdP. Those +users will then be able to accept invitations to join Kong Manager and log in +with their IdP credentials. + +If an admin's group changes in the IdP, their Kong admin account's associated +role also changes in {{site.base_gateway}} the next time they log in through Kong +Manager. The mapping removes the task of manually managing access in +{{site.base_gateway}}, as it makes the IdP the system of record. + +Here's how OIDC authenticated group mapping works: +1. Create roles in {{site.base_gateway}} using either the Kong Admin API or Kong +Manager. +2. Create groups and associate roles with the groups. +3. Configure the OIDC plugin to connect with your IdP. +4. When users log in to Kong Manager, they get permissions based on the IdP + group(s) they belong to. + +## Prerequisites +* An IdP with an authorization server and users with groups assigned +* [{{site.ee_product_name}} installed and configured](/gateway/{{page.release}}/install-and-run/) +* Kong Manager enabled +* RBAC enabled +* (If using Kubernetes) [Helm](https://helm.sh/docs/intro/install/) installed + +## Create Kong Groups and Assign Roles + +{:.note} +> **Note:** The following examples assume that you have RBAC enabled with +Basic Auth and are transitioning to OpenID Connect. + +{% navtabs %} +{% navtab Kong Manager %} + +Create a group and assign a role to it: + +1. Open **Teams** from the top navigation. +2. Click the **Groups** tab. +3. Click **Create New Group**. +4. Set the **Group Name** to match your IdP group. + + **Note:** Group names are case-sensitive. Make sure to match your IdP + group name exactly. + +5. (Optional) In the **Comment** field, enter a description for the group. +6. Click on **Add/Edit Roles**, then choose a workspace and a role. +7. Save the role assignment, then click **Create**. + +Create an admin for the group: +1. Open the **Teams** from the top navigation. +2. Click the **Admins** tab. +3. Click **Invite Admin**. +4. Enter a username and email, and optionally a custom ID to make the admin +easy for you to identify. + + **Note**: Make sure the username exactly matches the admin's name in + your IdP. + +5. Ensure the **Enable RBAC token** checkbox is checked. +6. Save the role assignment, then click **Invite Admin**. + +{% endnavtab %} +{% navtab Kong Admin API %} + +1. Create a group, making sure the group `name` parameter matches your IdP group +name: + + ```sh + $ curl -X POST --url http://localhost:8001/groups \ + --header 'content-type: application/json' \ + --header 'kong-admin-token: ' \ + --data '{ + "comment": "example group", + "name": "examplegroup" + }' + ``` + + **Note:** Group names are case-sensitive. Make sure to match your IdP group + name exactly. + +2. Assign a role to the group: + + ```sh + $ curl -X POST --url http://localhost:8001/groups/{group-id}/roles \ + --header 'content-type: application/json' \ + --header 'kong-admin-token: ' \ + --data '{ + "rbac_role_id": "e948171e-699c-4035-9b74-2b2b576d9644", + "workspace_id": "236bfa99-cf09-4389-afa8-e2bd6da89fd3" + }' + ``` + + Where: + * [`rbac_role_id`](/gateway/{{page.release}}/admin-api/rbac/reference/#list-roles): + UUID of the role you want to assign. + * [`workspace_id`](/gateway/{{page.release}}/admin-api/workspaces/reference/#list-workspaces): + UUID of the workspace to add the role to. + +3. Create an admin for the group: + + ```sh + $ curl -X POST --url http://localhost:8001/admins \ + --header 'content-type: application/json' \ + --header 'kong-admin-token: ' \ + --data '{ + "username": "", + "custom_id": "", + "email": "", + "rbac_token_enabled": true + }' + ``` + +{% endnavtab %} +{% endnavtabs %} + +Notice how in the instructions above, you did not assign a role to your +admin. The role will be matched with the role assigned to them in the IdP. + +## Apply OIDC Auth Mapping to {{site.base_gateway}} + +{% navtabs %} +{% navtab Kubernetes with Helm %} + +1. Create a configuration file for the OIDC plugin and save it as +`admin_gui_auth_conf`. For group mapping, you must include the +`authenticated_groups_claim` parameter as part of this configuration. + + For example, the configuration should look something like this: + + ```json + { + "issuer": "", + "client_id": [""], + "client_secret": [""], + "consumer_by": ["username","custom_id"], + "ssl_verify": false, + "consumer_claim": ["sub"], + "leeway": 60, + "redirect_uri": [""], + "login_redirect_uri": [""], + "logout_methods": ["GET", "DELETE"], + "logout_query_arg": "logout", + "logout_redirect_uri": [""], + "scopes": ["openid","profile","email","offline_access"], + "authenticated_groups_claim": ["groups"], + "auth_methods": ["authorization_code"] + } + ``` + + For detailed descriptions of all the parameters used here, and many other + customization options, see the [OpenID Connect parameter reference](/hub/kong-inc/openid-connect/#configuration-parameters). + +2. Create a secret from the file you just created: + + ```sh + $ kubectl create secret generic kong-idp-conf --from-file=admin_gui_auth_conf -n kong + ``` + +3. Update the RBAC section of the deployment `values.yml` file with the +following parameters: + + ```yaml + rbac: + enabled: true + admin_gui_auth: openid-connect + session_conf_secret: kong-session-conf + admin_gui_auth_conf_secret: kong-idp-conf + ``` + +4. Using Helm, upgrade the deployment with your YAML filename: + + ```sh + $ helm upgrade --install kong-ee kong/kong -f ./myvalues.yaml -n kong + ``` +{% endnavtab %} +{% navtab Docker %} + +If you have a Docker installation, run the following command to set the needed +environment variables and reload the {{site.base_gateway}} configuration. + +Substitute all variables in angled brackets (`< >`) with your own values: + +```sh +$ echo " + KONG_ENFORCE_RBAC=on \ + KONG_ADMIN_GUI_AUTH=openid-connect \ + KONG_ADMIN_GUI_AUTH_CONF='{ + \"issuer\": \"\", + \"client_id\": [\"\"], + \"client_secret\": [\"\"], + \"consumer_by\": [\"username\",\"custom_id\"], + \"ssl_verify\": false, + \"consumer_claim\": [\"sub\"], + \"leeway\": 60, + \"redirect_uri\": [\"\"], + \"login_redirect_uri\": [\"\"], + \"logout_methods\": [\"GET\", \"DELETE\"], + \"logout_query_arg\": \"logout\", + \"logout_redirect_uri\": [\"\"], + \"scopes\": [\"openid\",\"profile\",\"email\",\"offline_access\"], + \"authenticated_groups_claim\": [\"groups\"], + \"auth_methods\": [\"authorization_code\"] + }' kong reload exit" | docker exec -i /bin/sh +``` + +Replace `` with the ID of your container. + +{% endnavtab %} +{% navtab kong.conf %} + +1. Navigate to your `kong.conf` file. + +2. With RBAC enabled, add the `admin_gui_auth` and `admin_gui_auth_conf` +properties to the file: + + ``` + enforce_rbac = on + admin_gui_auth = openid-connect + admin_gui_auth_conf = { + "issuer": "", + "client_id": [""], + "client_secret": [""], + "consumer_by": ["username","custom_id"], + "ssl_verify": false, + "consumer_claim": ["sub"], + "leeway": 60, + "redirect_uri": [""], + "login_redirect_uri": [""], + "logout_methods": ["GET", "DELETE"], + "logout_query_arg": "logout", + "logout_redirect_uri": [""], + "scopes": ["openid","profile","email","offline_access"], + "authenticated_groups_claim": ["groups"], + "auth_methods": ["authorization_code"] + } + ``` + + For detailed descriptions of all the parameters used here, and many other + customization options, see the [OpenID Connect parameter reference](/hub/kong-inc/openid-connect/#configuration-parameters). + +3. Restart {{site.base_gateway}} to apply the file. + + ```sh + $ kong restart -c /path/to/kong.conf + ``` + +{% endnavtab %} +{% endnavtabs %} diff --git a/app/gateway/2.6.x/configure/auth/oidc-okta.md b/app/gateway/2.6.x/configure/auth/oidc-okta.md new file mode 100644 index 000000000000..b5f79f7d7f25 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/oidc-okta.md @@ -0,0 +1,125 @@ +--- +title: OpenID Connect with Okta +badge: enterprise +--- + +This guide covers an example OpenID Connect plugin configuration to authenticate browser clients using an Okta identity provider. + +For information about configuring OIDC using Okta as an Identity provider +in conjunction with the Application Registration plugin, see +[Set Up External Portal Application Authentication with Okta and OIDC](/gateway/{{page.release}}/developer-portal/administration/application-registration/okta-config). + +## Prerequisites + +Because OpenID Connect deals with user credentials, all transactions should take place over HTTPS. +Although user passwords for third party identity providers are only submitted to +those providers and not Kong, authentication tokens grant access to a subset of +user account data and protected APIs, and should be secured. As such, you should +make Kong's proxy available via a fully-qualified domain name and [add a certificate][add-certificate] for it. + +## Kong Configuration + +If you have not yet [added a **Route** and a **Service**][add-service], go ahead +and do so. Again, note that you should be able to secure this route with HTTPS, +so use a hostname you have a certificate for. Add a location handled by your route +as an authorized redirect URI in Okta (under the **Authentication** section of your app registration). + +## Okta IdP Configuration + +### Sample Okta Configuration Steps + +1. [Register an Application][okta-register-app]. Select the **Applications** page, click **Add Application**. + +2. Select **Web** as the platform. + +3. Fill out the Application's Settings. + + **Login re-direct URIs** is a URI that corresponds to a Route you have configured in Kong that will use Okta to authenticate. **Group Assignment** defines who is allowed to use this application. **Grant Type Allowed** indicates the Grant types to allow for your application. + +4. After submitting the Application configuration, the client credentials will display on the **General** page. + +5. [Define and configure an Authorization server][okta-authorization-server]. Select the **API** page and add an Authorization Server if you don't have an existing one to use. + +6. Click **Save** and view your Authorization Server Settings. + +## Plugin Configuration + +Add a plugin with the configuration below to your Route using an HTTP client or [Kong Manager][enable-plugin]. + +```bash +$ curl -i -X POST https://admin.kong.example/routes/ROUTE_ID/plugins --data name="openid-connect" \ + --data config.issuer="https://YOUR_OKTA_DOMAIN/oauth2/YOUR_AUTH_SERVER/.well-known/openid-configuration" \ + --data config.client_id="YOUR_CLIENT_ID" \ + --data config.client_secret="YOUR_CLIENT_SECRET" \ + --data config.redirect_uri="https://kong.com/api" \ + --data config.scopes="openid" \ + --data config.scopes="email" \ + --data config.scopes="profile" +``` + +Some of the configurations above must use values specific to your environment: + +* The `issuer` URL can be found from your Authorization Server settings. +* The `redirect_uri` should be the URI you specified earlier when configuring your app. +You can view and edit this from the **General** page for your application. +* For `client_id` and `client_secret`, replace `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` +with the client ID and secret shown in your Okta application's **General** page. + +Visiting a URL matched by that route in a browser will now redirect to Okta's authentication +site and return you to the redirect URI after authenticating. + +Additional plugin parameter to consider: + +* The `auth_methods` parameter defines a lists of all the authentication methods +that you want the plugin to accept. By default, its value is a list of all the supported methods. +It is advisable to define this parameter with only the methods you want to allow. + +### Access Restrictions + +The configuration above allows users to authenticate and access the Route even though +no Consumer was created for them: any user with a valid account in the directory +will have access to the Route. The OIDC plugin allows this as the simplest authentication option, +but you may wish to restrict access further. There are several options for this: + +- Consumer Mapping +- Pseudo-Consumer Mapping + +#### Consumer Mapping + +If you need to interact with other Kong plugins using consumer information, you +can add configuration that maps account data received from the identity provider to a Kong consumer. +For this example, the user's Okta's AD account GUID is mapped to a Consumer by setting it +as the `custom_id` on their consumer: + +```bash +$ curl -i -X POST http://admin.kong.example/consumers/ \ + --data username="Yoda" \ + --data custom_id="e5634b31-d67f-4661-a6fb-b6cb77849bcf" + +$ curl -i -X PATCH http://admin.kong.example/plugins/OIDC_PLUGIN_ID \ + --data config.consumer_by="custom_id" \ + --data config.consumer_claim="sub" +``` + +Now, if a user logs into an Okta account with the GUID `e5634b31-d67f-4661-a6fb-b6cb77849bcf`, Kong will apply configuration associated with the Consumer `Yoda` to their requests. + +This also requires that clients login using an account mapped to some Consumer, which might +not be desirable (e.g., you apply OpenID Connect to a service, but only use plugins +requiring a Consumer on some Routes). To deal with this, you can set the `anonymous` parameter +in your OIDC plugin configuration to the ID of a generic Consumer, which will +then be used for all authenticated users that cannot be mapped to some other Consumer. +You can alternately set `consumer_optional` to `true` to allow similar logins +without mapping an anonymous Consumer. + +#### Pseudo-consumers + +For plugins that typically require consumers, the OIDC plugin can provide a consumer ID based on the value of a claim without mapping to an actual Consumer. Setting `credential_claim` to a claim [in your plugin configuration][credential-claim] will extract the value of that claim and use it where Kong would normally use a consumer ID. Note that this may not work with all consumer-related functionality. + +Similarly, setting `authenticated_groups_claim` will extract that claim's value and use it as a group for the ACL plugin. + +[okta-authorization-server]: https://developer.okta.com/docs/guides/customize-authz-server/create-authz-server/ +[okta-register-app]: https://developer.okta.com/docs/guides/add-an-external-idp/openidconnect/register-app-in-okta/ +[add-certificate]: /gateway/latest/admin-api/#add-certificate +[add-service]: /gateway/{{page.release}}/admin-api/#service-object +[credential-claim]: /hub/kong-inc/openid-connect/#configcredential_claim +[enable-plugin]: /gateway/{{page.release}}/admin-api/#plugin-object diff --git a/app/gateway/2.6.x/configure/auth/oidc-use-case.md b/app/gateway/2.6.x/configure/auth/oidc-use-case.md new file mode 100644 index 000000000000..e0bc6cc41604 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/oidc-use-case.md @@ -0,0 +1,34 @@ +--- +title: OpenID Connect +badge: enterprise +--- + +## What does OpenID Connect do? + +OpenID Connect provides a way to form a *federation* with *identity providers*. Identity providers are third parties that store account credentials. If the identity provider authenticates a user, the application trusts that provider and allows access to the user. The *identity provider* bears some responsibility for protecting the user’s credentials and ensuring authenticity, so applications no longer need to on their own. + +Besides delegating responsibility to an identity provider, OpenID Connect also makes single sign-on possible without storing any credentials on a user’s local machine. + +Finally, enterprises may want to manage access control for many applications from one central system of record. For example, they may want employees to be able to access many different applications using their email address and password. They may want to also change access (e.g. if an employee separates or changes roles) from one central point. OpenID Connect addresses this challenge by providing a way for many different applications to authenticate users through the same third-party identity provider. + +## What does Kong’s OpenID Connect plugin do? + +Just as OpenID Connect enables developers to offload authentication to another party, Kong enables developers to separate entire processes from their applications. Rather than needing to hand write the code for OpenID Connect *within* a service, developers can place Kong in front of the service and have Kong handle authentication. This separation allows developers to focus on the business logic within their application. It also allows them to easily swap out services while preserving authentication at the front door, and to effortlessly spread the same authentication to *new* services. + +Kong users may prefer OpenID Connect to other authentication types, such as Key Auth and Basic Auth, because they will not need to manage the database storing passwords. Instead, they can offload the task to a trusted identity provider of their choice. + +While the OpenID Connect Plugin can suit many different use cases and extends to other Plugins such as JWT (JSON Web Token) and 0Auth 2.0, the most common use case is the Authorization Code flow. + +## References +See our series of integration guides to configure the OIDC plugin for your +identity provider: + + - [Auth0](/gateway/{{page.release}}/configure/auth/oidc-auth0/) + - [Amazon AWS Cognito](/gateway/{{page.release}}/configure/auth/oidc-cognito/) + - [Curity](/gateway/{{page.release}}/configure/auth/oidc-curity/) + - [Google](/gateway/{{page.release}}/configure/auth/oidc-google/) + - [Microsoft Azure Active Directory (Azure AD)](/gateway/{{page.release}}/configure/auth/oidc-azuread/) + - [Okta](/gateway/{{page.release}}/configure/auth/oidc-okta/) + + For a full list of tested providers and all available configuration options, + see the [OpenID Connect plugin reference](/hub/kong-inc/openid-connect/). diff --git a/app/gateway/2.6.x/configure/auth/rbac/add-admin.md b/app/gateway/2.6.x/configure/auth/rbac/add-admin.md new file mode 100644 index 000000000000..4c6d1110a166 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/rbac/add-admin.md @@ -0,0 +1,89 @@ +--- +title: Invite an Admin +badge: enterprise +--- + +An Admin is any user in Kong Manager. They may access +Kong entities within their assigned Workspaces based +on the Permissions of their Roles. + +This guide describes how to invite an Admin in Kong +Manager. As an alternative, if a Super Admin wants to +invite an Admin with the Admin API, it is possible to +do so using +[`/admins`](/gateway/{{page.release}}/admin-api/admins/reference/#invite-an-admin). + +## Invite an Admin + +1. Navigate to the **Teams** page in Kong Manager + +2. From the **Admins** tab select **Invite Admin** + +3. Fill out the username and email address. When a new **Admin** receives an +invitation, they will only be able to log in with that email address. Assign the appropriate **Role** and click **Invite User** to send the invitation. + + **Super Admins** can invite users to multiple **Workspaces**, and + assign them any **Role** available within **Workspaces**, including **Roles** that exist by default (e.g. `super-admin`, `read-only`) and **Roles** with customized permissions. + + The **Super Admin** can see all available roles across + **Workspaces** on the **Roles** tab of the **Organization** page. + + +4. On the **Teams** page, the new invitee will appear on the **Admins** list with the under **Invited**. Once they accept the invitation, the user will be listed in the main **Admins** list. + + By default, the registration link will expire after 259,200 + seconds (3 days). This time frame can be configured with the `kong.conf` + file in `admin_invitation_expiry`. + + If an email fails to send, either due to an incorrect email + address or an external error, it will be possible to resend an invitation. + + If SMTP is not enabled or the invitation email fails to send, + it is possible for the Super Admin to copy and provide a registration link + directly. + +5. The newly invited **Admin** will have the ability to set a password. If the **Admin** ever forgets the password, it is possible for them to reset it through a recovery email. + + +## Copy and Send a Registration Link + +If a mail server is not yet set up, it is still possible to invite Admins to register and log in. + +1. Invite an **Admin** as described in the section above. + +2. If the "View" link is clicked next to the invited Admin's name, a + `register_url` is displayed on the invitee's details page. + +3. Copy and directly send this link to the invited Admin so that they may set + up their credentials and log in. + +If `admin_gui_auth` is `ldap-auth-advanced`, credentials are not stored in Kong, and the Admin will be directed to log in. + +## How to Grant an Admin Access with LDAP + +1. Pick a user in the LDAP Directory that will be the Super Admin. + +2. Change the Super Admin’s username in Kong by making a `PATCH` request to +`admins/kong_admin` and setting the value of `username` to the corresponding +LDAP `attribute`. + +For example, if the LDAP user's attribute is `einstein`, +the `PATCH` to `/admins/kong_admin` should have a `username` set to `einstein`. + +3. Log in to Kong Manager using the LDAP credentials associated with the Super +Admin. + +4. Invite Admins from the "Admins" page in Kong Manager, ensuring that the +`username` of each Admin is mapped to the `attribute` value set in the LDAP +directory. + + To enable the Admins to log in, it is still necessary + to assign a Role to them. + +5. Once an Admin has logged in successfully and accesses the Admin API using +their LDAP credentials, they will be marked as “approved” on the "Admins" list +in Kong Manager + + The new Admins will still receive an email, but all + credentials will be handled through the LDAP server, not Kong Manager + or the Admin API. diff --git a/app/gateway/2.6.x/configure/auth/rbac/add-role.md b/app/gateway/2.6.x/configure/auth/rbac/add-role.md new file mode 100644 index 000000000000..75ceaff25bbc --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/rbac/add-role.md @@ -0,0 +1,61 @@ +--- +title: Add a Role and Permissions +badge: enterprise +--- + +Roles make it easy to logically group and apply the same +set of Permissions to Admins. Permissions may be +customized in detail, down to individual actions and endpoints. + +{{site.base_gateway}} includes default Roles for standard +use cases, e.g. inviting additional Super Admins, +inviting Admins that may only `read` endpoints. + +This guide describes how to create a custom Role in Kong +Manager for a unique use case. As an alternative, if a +Super Admin wants to create a Role with the Admin API, +it is possible to do so using +[`/rbac/roles`](/gateway/{{page.release}}/admin-api/rbac/reference/#add-a-role). +To add Permissions to the new Role, use +[`/rbac/roles/{name_or_id}/endpoints`](/gateway/{{page.release}}/admin-api/rbac/reference/#add-a-role-endpoint-permission) +for endpoints or +[`/rbac/roles/{name_or_id}/entities`](/gateway/{{page.release}}/admin-api/rbac/reference/#add-a-role-entity-permission) +for specific entities. + +## Prerequisites + +* [`enforce_rbac = on`](/gateway/{{page.release}}/reference/configuration/#enforce_rbac) +* {{site.base_gateway}} has [started](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/) +* Logged in to Kong Manager as a **Super Admin** + +## Add a role and permissions + +1. On the **Admins** page, to create a new **Role**, click the +**Add Role** button at the top right of the list of **Roles**. + +1. On the **Add Role** form, name the **Role** according to the +**Permissions** you want to grant. + + ![New Role naming](https://konghq.com/wp-content/uploads/2018/11/km-new-role.png) + + **Note:** It may be helpful for future reference to include + a brief comment describing the reason for the **Permissions** or + a summary of the **Role**. + +1. Click the **Add Permissions** button and fill out the form. Add the endpoint **Permissions** by marking the appropriate checkbox. + + ![New Role permissions](https://konghq.com/wp-content/uploads/2018/11/km-perms.png) + +1. Click **Add Permission to Role** to see the permissions listed on the form. + + ![New Role permissions list](https://konghq.com/wp-content/uploads/2018/11/km-perms-list.png) + +1. To forbid access to certain endpoints, click **Add Permission** +again and use the **negative** checkbox. + + ![Negative permissions](https://konghq.com/wp-content/uploads/2018/11/km-negative-perms.png) + +1. Submit the form and see the new **Role** appear on the +**Admins** page. + + ![Roles list](https://konghq.com/wp-content/uploads/2018/11/km-roles-list.png) diff --git a/app/gateway/2.6.x/configure/auth/rbac/add-user.md b/app/gateway/2.6.x/configure/auth/rbac/add-user.md new file mode 100644 index 000000000000..620ce980bd5a --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/rbac/add-user.md @@ -0,0 +1,60 @@ +--- +title: Create an RBAC User +badge: enterprise +--- + +## Admins vs. RBAC Users + +| | Admin API | Kong Manager | +|------------|-----------|--------------| +| Admins | ✔️ | ✔️ | +| RBAC Users | ✔️ | X | + + +An RBAC User has the ability to access the {{site.base_gateway}} Admin API. The Permissions assigned to their Role will define the types of actions they can perform with various Admin API objects. + +An [Admin](/gateway/{{page.release}}/configure/auth/kong-manager/), like an RBAC User, has the ability to access the {{site.base_gateway}} Admin API. The Admin also has the ability log in to Kong Manager. Like an RBAC User, an Admin’s Role will determine the types of actions it can perform—except that they will also have the ability to benefit from Kong Manager’s interface and visualizations. + +If creating a *service account* for {{site.base_gateway}}, e.g., for a machine as part of an automated process, then an RBAC User is adequate. + +If creating a *personal account* for {{site.base_gateway}}, then Admin may be preferable since it also has access to Kong Manager. + +## Prerequisites + +* Authentication and RBAC are [enabled](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/) +* [Logged in as the Super Admin](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/) +or a user that has `/admins` and `/rbac` read and write access. + +## How to Add an RBAC User in Kong Manager + +1. From the dashboard, click the **Teams** tab in the top navigation menu. + +2. On the **Teams** page, click the **RBAC Users** tab. + +3. Using the dropdown menu, select which **Workspace** the new user has access to. + + >Note: The **Default Workspace** is global, meaning the RBAC User with access to default has access to entities across all other Workspaces. This Workspace assignment is useful for administrative and auditing accounts, but not for members of specific teams. + +4. Click the **Add New User** button to the right of the dropdown menu to open the registration form. + +5. In the **Add New User** registration form provide a Name, User Token, Comment, and Enablement + + The name of the RBAC User must be globally unique, even if two users are in different Workspaces, and it cannot have the same as an Admin account. + + These naming conventions are important if using OIDC, LDAP, or another external method of identity and access management. + + The RBAC User account is enabled by default, if you want the RBAC User account to start in a disabled state and enable it later, uncheck the box. + +6. Click the **Add User Roles** button in the **Role(s) per workspace** section. Select the Role (or Roles) desired for the new RBAC User. + + If the RBAC User has no Roles assigned, it will not have permission to access any objects. + + An RBAC User’s Role assignments may be altered later if needed. + + The Roles can only belong to one Workspace, as selected in Step 3. + + To provide an RBAC User with access to objects in multiple Workspaces, see Step 3. + +7. Click **Create User** to complete the user registration. + + The page will automatically redirect back to the **Teams** page, where the new user is listed. diff --git a/app/gateway/2.6.x/configure/auth/rbac/index.md b/app/gateway/2.6.x/configure/auth/rbac/index.md new file mode 100644 index 000000000000..68a551c21668 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/rbac/index.md @@ -0,0 +1,60 @@ +--- +title: RBAC in Kong Manager +badge: enterprise +--- + +In addition to authenticating Admins and segmenting Workspaces, +{{site.base_gateway}} has the ability to enforce Role-Based Access Control +(RBAC) for all resources with the use of Roles assigned to Admins. + +As the Super Admin (or any Role with read and write +access to the `/admins` and `/rbac` endpoints), it is possible to +create new Roles and customize Permissions. + +In Kong Manager, RBAC affects how Admins are able to navigate +through the application. + +### Default Roles + +Kong includes Role-Based Access Control (RBAC). Every Admin using Kong Manager +will need an assigned Role based on the resources they have Permission to access. + +When a Super Admin starts Kong for the first time, the `default` Workspace will +include three default Roles: `read-only`, `admin`, and `super-admin`. The three +Roles have Permissions related to every Workspace in the cluster. + +Similarly, if a Role is confined to certain Workspaces, the Admin assigned to it +will not be able to see either the overview or links to other Workspaces. + +If a Role does not have Permission to access entire endpoints, +the Admin assigned to the Role will not be able to see the related navigation links. + +{:.important} +> Important: Although a default Admin has full permissions with every +endpoint in Kong, only a Super Admin has the ability to assign and modify RBAC Permissions. An Admin is not able to modify their own Permissions or delimit a Super Admin's Permissions. + +### How RBAC rules work in {{site.base_gateway}} + +Although there are concepts like groups and roles in {{site.base_gateway}}, when determining if a user has sufficient permissions to access the endpoint, combinations of workspace and endpoint are collected from roles and groups assigned to a user, being the minimal unit for {{site.base_gateway}} to check for permissions. These combinations will be referred to as “rules” in the following paragraphs. + +{{site.base_gateway}} uses a precedence model, from most specificity to least specificity, to determine if a user has access to an endpoint. For each request {{site.base_gateway}} checks for an RBAC rule assigned to the requesting user in the following order: + +* An allow or deny rule against the current endpoint in the current workspace + +* An allow or deny rule against the current endpoint in any workspace (`*`) + +* An allow or deny rule against any endpoint (`*`) in the current workspace + +* An allow or deny rule against any endpoint (`*`) in any workspace (`*`) + +If {{site.base_gateway}} finds a matching rule for the current user, endpoint, and workspace it allows or denies the request according to +that rule. Once {{site.base_gateway}} finds an applicable rule, it stops, and does not continue checking for less specific rules. If no rules are found, the request is denied. + +The default admin roles define permissions for any workspace is (`*`). +{{site.base_gateway}} stops at the first role, which means any role assigned in the default workspace has permissions to all subsequently created workspaces unless roles +in specific workspaces are explicitly assigned. When roles across multiple workspaces are assigned, roles in workspaces +other than default take precedent. For example, a user assigned to the `super-admin` role in the default workspace as well +as the `workspace-read-only` role in the `ws` workspace has full permissions to endpoints in all workspaces except the `ws` workspace. The user only has read-only permissions to endpoints in the `ws` workspace. + +{{site.base_gateway}} allows you to add negative rules to a role. A negative rule denies actions associated with the endpoint. +Meanwhile, a negative rule precedes other non-negative rules while following the above rules. diff --git a/app/gateway/2.6.x/configure/auth/service-directory-mapping.md b/app/gateway/2.6.x/configure/auth/service-directory-mapping.md new file mode 100644 index 000000000000..8ae723821d52 --- /dev/null +++ b/app/gateway/2.6.x/configure/auth/service-directory-mapping.md @@ -0,0 +1,162 @@ +--- +title: Mapping LDAP Service Directory Groups to Kong Roles +badge: enterprise +--- + +Service Directory Mapping allows organizations to use their LDAP Directory for authentication and authorization in {{site.base_gateway}}. + +After starting {{site.base_gateway}} with the desired configuration, you can create new Admins whose usernames match those in your LDAP directory. Those users will then be able to accept invitations to join Kong Manager and log in with their LDAP credentials. + +How Service Directory Mapping works in Kong: +* Roles are created in {{site.base_gateway}} using the Admin API or Kong Manager. +* Groups are created and roles are associated with the groups. +* When users log in to Kong Manager, they get permissions based on the group(s) they belong to. + +For example, if a User's Group changes in the Service Directory, their Kong Admin account's associated Role also changes in {{site.base_gateway}} the next time they log in to Kong Manager. The mapping removes the task of manually managing access in {{site.base_gateway}}, as it makes the Service Directory the system of record. + +## Prerequisites + +* {{site.base_gateway}} installed and configured +* Kong Manager access +* A local LDAP directory + +## Configure Service Directory Mapping + +Configure Service Directory Mapping to use your LDAP Directory for authentication and authorization. + +## Start {{site.base_gateway}} + +From a terminal window, enter: + +``` +$ kong start [-c /path/to/kong/conf] +``` + +## Enable LDAP Authentication and enforce RBAC + +To enable LDAP Authentication and enforce RBAC for Kong Manager, configure Kong with the following properties: + +``` +admin_gui_auth = ldap-auth-advanced +enforce_rbac = on +``` + +**Note**: When enabling LDAP Authentication in this step, you are enabling and configuring the LDAP Authentication Advanced Plugin for Kong Manager. No other configuration for the plugin is needed. + +## Configure the Sessions plugin + +Configure the Sessions Plugin for Kong Manager: + +``` +admin_gui_session_conf = { "secret":"set-your-string-here" } +``` + +>Note: The **Sessions Plugin** requires a **secret** and is configured securely by default: + +* Under all circumstances, the secret must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to false. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. Learn more about these properties in [_Session Security in Kong Manager_](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/), and see [_example configurations_](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +## Configure LDAP Authentication for Kong Manager + +Configure LDAP Authentication for Kong Manager with the following properties. Note the attribute variables are defined below: + +``` +admin_gui_auth_conf = { + "anonymous":"", \ + "attribute":"", \ + "bind_dn":"", \ + "base_dn":"", \ + "cache_ttl": 2, \ + "header_type":"Basic", \ + "keepalive":60000, \ + "ldap_host":"", \ + "ldap_password":"", \ + "ldap_port":389, \ + "start_tls":false, \ + "timeout":10000, \ + "verify_ldap_host":true, \ + "consumer_by":["username", "custom_id"], \ + "group_base_dn":"", + "group_name_attribute":"", + "group_member_attribute":"", +} +``` + +* `attribute`:``: The attribute used to identify LDAP users + * For example, to map LDAP users to admins by their username, `attribute":"uid` +* `bind_dn`:``: LDAP Bind DN (Distinguished Name) + * Used to perform LDAP search of user. This `bind_dn` should have permissions to search for the user being authenticated. + * For example, `uid=einstein,ou=scientists,dc=ldap,dc=com` +* `base_dn`:``: LDAP Base DN (Distinguished Name) + * For example, `ou=scientists,dc=ldap,dc=com` +* `ldap_host`:``: LDAP host domain. + * For example, `ec2-XX-XXX-XX-XXX.compute-1.amazonaws.com` +* `ldap_port`: The default LDAP port is 389. 636 is the port required for SSL LDAP and AD. + If `ldaps` is configured, you must use port 636. For more complex Active Directory (AD) environments, + instead of Domain Controller and port 389, consider using a Global Catalog host and port, which is port 3268 by default. +* `ldap_password`:``: LDAP password + * *Important*: As with any configuration property, sensitive information may be set as an environment variable instead of being written directly in the configuration file. +* `group_base_dn`:``: Sets a distinguished name for the entry where LDAP searches for groups begin. The default is the value from `conf.base_dn`. +* `group_name_attribute`: ``: Sets the attribute holding the name of a group, typically called `name` (in Active Directory) or `cn` (in OpenLDAP). The default is the value from `conf.attribute`. +* `group_member_attribute`:``: Sets the attribute holding the members of the LDAP group. The default is `memberOf`. + +## Define Roles with Permissions + +Define Roles with Permissions in {{site.base_gateway}}, using the Admin API's [_RBAC endpoints_](/gateway/{{page.release}}/admin-api/rbac/reference/#update-or-create-a-role) or using Kong Manager's Teams > [Admins tab](/gateway/{{page.release}}/configure/auth/rbac/add-user/). You must manually define which Kong Roles correspond to each of the Service Directory's Groups using either of the following: + +In Kong Manager's Directory Mapping section. Go to Teams > Groups tab. +With the Admin API's Directory Mapping endpoints. + +{{site.base_gateway}} will not write to the Service Directory, for example, a {{site.base_gateway}} Admin cannot create Users or Groups in the directory. You must create Users and Groups independently before mapping them to {{site.base_gateway}}. + +## User-Admin Mapping + +To map a Service Directory User to a Kong Admin, you must configure the Admin's username as the value of the User's name from their LDAP Distinguished Name (DN) corresponding the attribute configured in `admin_gui_auth_conf`. Creating an Admin account in [_Kong Manager_](/gateway/{{page.release}}/configure/auth/rbac/add-admin/) or using the [_Admin API_](/gateway/{{page.release}}/admin-api/admins/reference/#invite-an-admin). + +For instructions on how to pair the bootstrapped Super Admin with a Directory User, see [_How to Set Up a Service Directory User as the First Super Admin_](/gateway/{{page.release}}/configure/auth/service-directory-mapping/#set-up-a-directory-user-as-the-first-super-admin). + +If you already have Admins with assigned Roles and want to use Group mapping instead, it is necessary to first remove all of their Roles. The Service Directory will serve as the system of record for User privileges. Assigned Roles will affect a user's privileges in addition to any roles mapped from Groups. + +## Group-Role Assignment + +Using Service Directory Mapping, Groups to Roles are mapped. When a user logs in, they are identified with their Admin username and then authenticated with the matching User credentials in the Service Directory. The Groups in the Service Directory are then automatically matched to the associated Roles that the organization has defined. + +### Example + +1. Wayne Enterprises maps the Service Directory Group, T1-Mgmt, to the Kong Role super-admin. +2. Wayne Enterprises maps a Service Directory User, named bruce-wayne, to a Kong Admin account with the same name, bruce-wayne. +3. The User, bruce-wayne, is assigned to the Group T1-Mgmt in the LDAP Directory. + + +When bruce-wayne logs in as an Admin to Kong Manager, they will automatically have the Role of super-admin as a result of the mapping. + +If Wayne Enterprises decides to revoke bruce-wayne's privileges by removing their assignment to T1-Mgmt, they will no longer have the super-admin Role when they attempt to log in. + +## Set Up a Directory User as the First Super Admin + +**Important**: Setting up a Directory User as the first Super Admin is recommended by Kong. + + +The following is an example of setting up a Directory User as the first Super Admin. +The example shows an attribute is configured with a unique identifier (UID), and the Directory User you want to make the Super Admin has a distinguished name (DN) entry of `UID=bruce-wayne`: + +``` +HTTPie +$ http PATCH :8001/admins/kong_admin username="bruce-wayne" +Kong-Admin-Token: +cURL +$ curl --request 'PATCH' --header 'Kong-Admin-Token: ' --header +'Content-Type: application/json' --data '{"username":"bruce-wayne"}' +'localhost:8001/admins/kong_admin' +``` + +This User will be able to log in, but until you map a Group belonging to bruce-wayne to a Role, the User will only use the Directory for authentication. Once you map the super-admin Role to a Group that bruce-wayne is in, then you can delete the super-admin Role from the bruce-wayne Admin. Note the group you pick needs to be “super” in your directory, otherwise as other admins log in with a generic group, for example the “employee” group, they will also become super-admins. + +**Important**: If you delete the super-admin Role from your only Admin, and have not yet mapped the super-admin Role to a Group that Admin belongs to, then you will not be able to log in to Kong Manager. + +Alternatives: + +* Start Kong with RBAC turned off, map a Group to the super-admin Role, and then create an Admin to correspond to a User belonging to that Group. Doing so ensures that the Super Admin's privileges are entirely tied to the Directory Group, whereas bootstrapping a Super Admin only uses the Directory for authentication. + +Create all Admin accounts for matching Directory Users and ensure that their existing Groups map to appropriate Roles before enforcing RBAC. diff --git a/app/gateway/2.6.x/configure/graphql-quickstart.md b/app/gateway/2.6.x/configure/graphql-quickstart.md new file mode 100644 index 000000000000..4c79694b6d5a --- /dev/null +++ b/app/gateway/2.6.x/configure/graphql-quickstart.md @@ -0,0 +1,62 @@ +--- +title: Getting Started with GraphQL and Kong Gateway +badge: enterprise +--- + +GraphQL decouples apps from services by introducing a flexible query language. Instead of a custom API for each screen, app developers describe the data they need, service developers describe what they can supply, and GraphQL automatically matches the two together. Teams ship faster across more platforms, with new levels of visibility and control over the use of their data. To learn more about how teams benefit, read why [GraphQL is important](https://www.apollographql.com/why-graphql/). + +{{site.base_gateway}} is an API gateway and platform. That means it is a form of middleware between computing clients and your API-based applications. {{site.base_gateway}} quickly and consistently extends the features of your APIs. Some of the popular features deployed through {{site.base_gateway}} include authentication, security, traffic control, serverless, analytics & monitoring, request/response transformations, and logging. To learn more about these features, see the [Hub page](/hub/) for plugins. For more about the benefits of Kong in general, please see the [FAQ](https://konghq.com/faqs). + +The GraphQL paradigm differs from traditional API-based systems. Depending on the resolver implementation details, one query can potentially generate an arbitrary number of requests. Proxy caching and rate limiting on top of GraphQL is key but usually overlooked as a hard problem to solve, since traditional proxy-caching and rate-limiting is not a good fit for GraphQL. + +Kong easily integrates with existing GraphQL infrastructure out of the box. By introspecting the GraphQL schema and queries, Kong provides enterprise-grade proxy-caching and rate-limiting specifically tailored for GraphQL. + +## Existing GraphQL infrastructure + +Use {{site.base_gateway}} to protect and manage an existing GraphQL endpoint. The following will set up a {{site.base_gateway}} instance on top of a GraphQL upstream and set up key-auth, proxy-caching and rate-limiting. + +### Add your Service and Route on Kong + +After installing and starting {{site.base_gateway}}, use the Admin API on port 8001 to add a new Service and Route. In this example, {{site.base_gateway}} will reverse proxy every incoming request with the specified incoming host to the associated upstream URL. You can implement very complex routing mechanisms beyond simple host matching. + + +``` +$ curl -i -X POST \ + --url http://localhost:8001/services/ \ + --data 'name=graphql-service' \ + --data 'url=http://example.com' +$ curl -i -X POST \ + --url http://localhost:8001/services/graphql-service/routes \ + --data 'hosts[]=example.com' \ +``` + +### Add GraphQL Plugins on the Service + +Proxy caching for GraphQL provides advanced caching over queries. + +``` +$ curl -i -X POST \ + --url http://localhost:8001/services/graphql-service/plugins/ \ + --data 'name=graphql-proxy-cache-advanced' \ + --data 'config.strategy=memory' +``` + +Protect your upstream GraphQL service with rate limiting. By introspecting your schema, it will analyze query costs and provide an enterprise-grade rate-limiting strategy. + +``` +$ curl -i -X POST http://localhost:8001/services/graphql-service/plugins \ + --data name=graphql-rate-limiting-advanced \ + --data config.limit=100,10000 \ + --data config.window_size=60,3600 \ + --data config.sync_rate=10 +``` + +The GraphQL Rate Limiting Advanced plugin supports two rate-limiting strategies. The default strategy will try to estimate cost on queries by counting the nesting of nodes. The default strategy is meant as a good middle ground for general GraphQL queries, where it's difficult to assert a clear cost strategy, so every operation has a cost of 1. + +A more advanced strategy is available for GraphQL schemas that enforce quantifier arguments on any connection, providing a good approximation on the number of nodes visited for satisfying a query. Any query without decorated quantifiers has a cost of 1. It is roughly based on [GitHub's GraphQL resource limits](https://developer.github.com/v4/guides/resource-limitations/). + +Read more about rate-limiting here: [GraphQL Rate Limiting Advanced Plugin](/hub/kong-inc/graphql-rate-limiting-advanced/) + +### New upstream + +We have prepared a [quickstart guide](https://github.com/Kong/kong-apollo-quickstart) that will help you build your new GraphQL service on top of Kong and Apollo. diff --git a/app/gateway/2.6.x/configure/grpc.md b/app/gateway/2.6.x/configure/grpc.md new file mode 100644 index 000000000000..56cbe14e3edc --- /dev/null +++ b/app/gateway/2.6.x/configure/grpc.md @@ -0,0 +1,170 @@ +--- +title: Introduction to Kong gRPC Plugins +--- + +Before going into the specifics of configuring Kong's gRPC plugins, let's +discuss the advantages of the gRPC protocol. Unlike JSON, +[gRPC](https://en.wikipedia.org/wiki/GRPC) +is a binary protocol, using [protobuf](https://en.wikipedia.org/wiki/Protocol_Buffers) +definitions to instruct how the data is marshalled and unmarshalled. Because +binary data is used instead of text, it's a more efficient way to transmit data +over a network. However, this also makes gRPC harder to work with, because inspecting +what went wrong is more challenging. Additionally, few clients natively handle gRPC. + +To help alleviate the challenges of working with gRPC, Kong has two plugins: +- [gRPC-Gateway](/hub/kong-inc/grpc-gateway/) +- [gRPC-Web](/hub/kong-inc/grpc-web/) + +The gRPC-Gateway plugin allows you to send JSON requests to a gRPC service. A +specially configured `.proto` file handles the conversion of the JSON request +into one that the gRPC service can handle. This allows you to expose RESTful-style +interfaces that talk to a gRPC service. + +The gRPC-Web plugin allows you to interact with a gRPC service from a browser. +Instead of presenting a RESTful-type call, you POST data to the same +gRPC service endpoint that the protobuf defines. + +For flexibility and compatibility with RESTful expectations, the gRPC-Gateway +plugin offers more configurability, whereas the gRPC-Web plugin adheres more +directly to the protobuf specification. + +Let's walk through setting up each plugin so you can see how they work. + +## gRPC-Gateway plugin configuration + +Set up a Service: + +``` +curl -X POST kong-cp-host:8001/services \ +--data 'name=grpcbin-service' \ +--data 'url=grpc://grpcb.in:9000' +``` + +Set up the Route to the Service: + +``` +curl -X POST kong-cp-host:8001/services/grpcbin-service/routes \ +--data 'name=grpcbin-get-route' \ +--data 'paths=/' \ +--data 'methods=GET' \ +--data 'headers.x-grpc=true' +``` + +Set up the gRPC-Web plugin: + +``` +curl -X POST kong-cp-host:8001/routes/grpcbin-get-route/plugins \ +--data 'name=grpc-gateway' \ +--data 'config.proto=/usr/local/kong/hello-gateway.proto' +``` + +Protobuf definition (`hello-gateway.proto`): + +``` +syntax = "proto3"; + +package hello; + +service HelloService { + rpc SayHello(HelloRequest) returns (HelloResponse) { + option (google.api.http) = { + get: "/v1/messages/{name}" + additional_bindings { + get: "/v1/messages/legacy/{name=**}" + } + post: "/v1/messages/" + body: "*" + } + } +} + + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloResponse { + string message = 1; +} +``` + +Upload the protobuf definition to your Kong Node: + +``` +docker cp hello-gateway.proto kong-dp-host:/usr/local/kong/ +``` + +Test your setup: + +``` +curl -X GET kong-dp-host:8000/v1/messages/kong2.1 \ +--header 'x-grpc: true' +``` + +## gRPC-Web plugin configuration + +Set up a Service: + +``` +curl -X POST kong-cp-host:8001/services \ +--data 'name=grpcbin-service' \ +--data 'url=grpc://grpcb.in:9000' +``` + +Set up the Route to the Service: + +``` +curl -X POST kong-cp-host:8001/services/grpcbin-service/routes \ +--data 'name=grpcbin-post-route' \ +--data 'paths=/' \ +--data 'methods=POST' \ +--data 'headers.x-grpc=true' +``` + +Set up the gRPC-Web plugin: + +``` +curl -X POST kong-cp-host:8001/routes/grpcbin-post-route/plugins \ +--data 'name=grpc-web' \ +--data 'config.proto=/usr/local/kong/hello.proto' +``` + +Protobuf definition (`hello.proto`): + +``` +syntax = "proto2"; + +package hello; + +service HelloService { + rpc SayHello(HelloRequest) returns (HelloResponse); + rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse); + rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse); + rpc BidiHello(stream HelloRequest) returns (stream HelloResponse); +} + +message HelloRequest { + optional string greeting = 1; +} + +message HelloResponse { + required string reply = 1; +} +``` + +Upload the protobuf definition to your Kong Node: + +``` +docker cp hello.proto kong-dp-host:/usr/local/kong/ +``` + +Test your setup: + +``` +curl -X POST kong-dp-host:8000/hello.HelloService/SayHello \ +--header 'x-grpc: true' \ +--header 'Content-Type: application/json' \ +--data '{"greeting":"kong2.1"}' +``` diff --git a/app/gateway/2.6.x/configure/logging.md b/app/gateway/2.6.x/configure/logging.md new file mode 100644 index 000000000000..fb656b2e23cd --- /dev/null +++ b/app/gateway/2.6.x/configure/logging.md @@ -0,0 +1,144 @@ +--- +title: Logging Reference +--- + +## Log Levels + +Log levels are set in [Kong's configuration](/gateway/{{page.release}}/reference/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. + +`notice` is the default and recommended log level. 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 in the [Configuration Property reference](/gateway/{{page.release}}/reference/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 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';`. 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 `proxy_access_log` by either editing `etc/kong/kong.conf` or 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/gateway/2.6.x/configure/network.md b/app/gateway/2.6.x/configure/network.md new file mode 100644 index 000000000000..7490bbbcb503 --- /dev/null +++ b/app/gateway/2.6.x/configure/network.md @@ -0,0 +1,71 @@ +--- +title: Network and Firewall +--- + +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]. + +{% include_cached /md/admin-listen.md release=page.release desc='short' %} + +* `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]: /gateway/{{page.release}}/reference/configuration/#proxy_listen +[stream_listen]: /gateway/{{page.release}}/reference/configuration/#stream_listen +[admin_listen]: /gateway/{{page.release}}/reference/configuration/#admin_listen +[secure_admin_api]: /gateway/{{page.release}}/admin-api/secure-admin-api diff --git a/app/gateway/2.6.x/developer-portal/administration/application-registration/3rd-party-oauth.md b/app/gateway/2.6.x/developer-portal/administration/application-registration/3rd-party-oauth.md new file mode 100644 index 000000000000..459510b78ea6 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/administration/application-registration/3rd-party-oauth.md @@ -0,0 +1,151 @@ +--- +title: Third-party OAuth2 Support for Application Registration +badge: enterprise +--- + +Third-party OAuth2 support allows developers to centralize application +credentials management with the [supported Identity Provider](#idps) of their +choice. To use the external IdP feature, set the `portal_app_auth` +configuration option to `external-oauth2` in the +`kong.conf.default` configuration file. For more information, see setting the +[Authorization Provider Strategy](/gateway/{{page.release}}/developer-portal/administration/application-registration/auth-provider-strategy). + +The Kong [OIDC](/hub/kong-inc/openid-connect/) and +[Portal Application Registration](/hub/kong-inc/application-registration/) +plugins are used in conjunction with each other on a Service: + +* The OIDC plugin handles all aspects of the OAuth2 handshake, including +looking up the Consumer via +[custom claim](/gateway/{{page.release}}/developer-portal/administration/application-registration/okta-config#auth-server-cclaim) +(the `custom_id` matches the identity provider `client_id` claim). + +* The Application Registration plugin is responsible for checking the mapped +Consumer and ensuring the Consumer has the correct ACL (Access Control List) +permissions to access the Route. + +## Supported identity providers {#idps} + +The Kong OIDC plugin supports many identity providers out of the box. The +following providers have been tested for the current version of the Kong +Portal Application Registration plugin used in tandem with the Kong OIDC plugin: + +* [Okta](https://developer.okta.com/). See the + [Okta setup example](/gateway/{{page.release}}/developer-portal/administration/application-registration/okta-config/). +* [Azure](https://azure.microsoft.com/). See the + [Azure setup example](/gateway/{{page.release}}/developer-portal/administration/application-registration/azure-oidc-config/). +* [Ping Identity](https://www.pingidentity.com/). + +### Resources + +How you authenticate with a Service depends on its underlying OAuth2 +implementation. For more information, reference the documentation below for +your implemented identity provider and OAuth flow. + +- Okta + - [Authorization Code Flow](https://developer.okta.com/docs/guides/implement-auth-code/overview/) + - [Authorization Code Flow (PKCE)](https://developer.okta.com/docs/guides/implement-auth-code-pkce/overview/) + - [Client Credentials Flow](https://developer.okta.com/docs/guides/implement-client-creds/overview/) + - [Implicit Grant Flow](https://developer.okta.com/docs/guides/implement-implicit/overview/) + +- Azure + - [Authorization Code Flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow) + - [Client Credentials Flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow) + - [Implicit Grant Flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow) + +- Ping Identity + - [Oauth2 Developers Guide](https://www.pingidentity.com/developer/en/resources/oauth-2-0-developers-guide.html) + +## Supported OAuth flows + +* Client Credentials ([RFC 6742 Section 4.4](https://tools.ietf.org/html/rfc6749#section-4.4)) +* Authorization Code ([RFC 6742 Section 4.1](https://tools.ietf.org/html/rfc6749#section-4.1)) +* Implicit Grant ([RFC 6742 Section 4.2](https://tools.ietf.org/html/rfc6749#section-4.2)) +* Password Grant ([RFC 6742 Section 4.3](https://tools.ietf.org/html/rfc6749#section-4.3)) + +Password Grant and [Implicit Grant flows](https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead) are available but not recommended +because they are less secure than the Authorization Code and Client Credentials +flows. + +### Client Credentials Flow {#cc-flow} + +The OIDC plugin makes authenticating using Client Credentials very +straightforward. This flow should be used for server-side and secure +machine-to-machine communication. The Client Credentials flow requires the +authorizing party to store and send the application's `client_secret`. + +In this flow, a developer makes a request against the Service with the OIDC and Application +Registration plugins applied. This request should contain the `client_id` and +`client_secret` as a Basic Auth authentication header: + +`Authorization: Basic client_id:client_secret` + +The `client_id:client_secret` should be base64-encoded. + +The following sequence diagram illustrates the Client Credentials flow through +the OIDC and Application Registration plugins. Click on the image to expand its + view. + +![Client Credentials Flow](/assets/images/products/gateway/dev-portal/dp-appreg-3rdparty-ccflow.png) + +| Step | Explanation | +|:------|:---------------------------------------------------------------------| +| a | Developer sends the Okta application's `client_id` and `client_secret` to the Route. The OIDC plugin proxies this request to the Okta auth server's endpoint.| +| b | Okta reads the `client_id` and `client_secret` and generates an access token. The auth server is configured to insert a custom claim `application_id`, which is a key/value pair with the Okta application's `client_id`. | +| c | Okta returns the access token to Kong. | +| d | The OIDC plugin reads the resulting access token and associates the request with the application via the `application_id` custom claim. | +| e | If the resolved application has permission to consume the Service via its Portal Application Registration plugin, Kong forwards the request to the Upstream. | + +### Authorization Code Flow {#ac-flow} + +Due to limitations of the OIDC plugin, a single plugin instance cannot handle +dynamic `client_id's` provisioned from multiple sources (applications). +To circumvent this issue, the IdP Issuer URL is exposed to developers on the +Dev Portal application show page when +[`show_issuer`](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration#app-reg-params) is enabled in the +Application Registration plugin. Developers can hit the Issuer URL directly to +provision an access token. After getting the access token, requests can be made +against the proxy. + +1. Set up the application to secure an access token against the IdP directly. +For more information about implementing the Authorization Code flow with Okta, +refer to the +[Okta developer guide](https://developer.okta.com/docs/guides/implement-auth-code/overview/). + +2. After the initial access token handshake has been completed, make subsequent +requests to the Kong service using that access token as a +[bearer token](https://tools.ietf.org/html/rfc6750#section-2.1). After +the first successful request, the OIDC plugin will establish a session with the +client so that the access token does not need to be continually passed with +every request. + +The following sequence diagram illustrates the Authorization Code flow through +the OIDC and Application Registration plugins. Click on the image to expand its + view. + +![Authorization Code Flow](/assets/images/products/gateway/dev-portal/dp-appreg-3rdparty-authcodeflow.png) + +| Step | Explanation | +|:------|:--------------------------------------------------------------------| +| a | A developer copies the target Service's `issuer_id`, which can be exposed in the Dev Portal application view Service Details page. Developers can configure their application to make a request to this endpoint to authenticate the user and retrieve an access token. | +| b | Okta redirects the user to a login page. | +| c | The user inputs their Single Sign-On (SSO) information. | +| d | The user submits the SSO form that contains their Okta username and password. | +| e | Upon a successful login, the application is given an access token to make against calls for all subsequent requests. | +| f | The user makes a request to the protected Service and Route.| +| g | The OIDC plugin takes the access token and runs introspection, consulting the Okta authorization server if necessary. After the access token has been verified, the plugin matches the custom claim to find the associated application Consumer via its `custom_id`. | +| h | The request is passed to the Application Registration plugin, which checks to make sure the Consumer has the appropriate ACL (Access Control List) permissions. | +| i | The request is proxied to the Upstream. | + +### Implicit Grant Flow + +The Implicit Grant flow is not recommended if the Authorization Code flow is +possible. + +1. Set up the application to secure an access token against the IdP directly. +For more information about implementing the Implicit Grant flow with Okta, refer to +the [Okta developer guide](https://developer.okta.com/docs/guides/implement-implicit/use-flow/). + +2. After the access token handshake has been completed, make subsequent requests +to the Kong service using that access token as a bearer token. After the first +successful request, the OIDC plugin will establish a session with the client so +that the access token does not need to be passed continuously. diff --git a/app/gateway/2.6.x/developer-portal/administration/application-registration/auth-provider-strategy.md b/app/gateway/2.6.x/developer-portal/administration/application-registration/auth-provider-strategy.md new file mode 100644 index 000000000000..238665831431 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/administration/application-registration/auth-provider-strategy.md @@ -0,0 +1,74 @@ +--- +title: Authorization Provider Strategy for Application Registration +badge: enterprise +--- + +You can use {{site.base_gateway}} or an external system of record with the +Application Registration plugin. + +The `portal_app_auth` configuration option must be set in `kong.conf` to enable +the Dev Portal Application Registration plugin with your chosen +authorization strategy: + +* `kong-oauth2`: Default. {{site.base_gateway}} is the system of record. The Application + Registration plugin is used in conjunction with the [OAuth2](/hub/kong-inc/oauth2/) or + [Key Authentication](/hub/kong-inc/key-auth/) plugin. + + {:.note} + > **Note**: The OAuth2 plugin can only be used with + traditional deployments. Because the OAuth2 plugin requires a database + for every gateway instance, it can't be used with hybrid mode or DB-less + deployments. + +* `external-oauth2`: An external IdP is the system of record. The + Portal Application Registration plugin is used in conjunction with the + [OpenID Connect (OIDC)](/hub/kong-inc/openid-connect/) plugin. + The `external-oauth2` option can be used with any deployment type. + + The third-party authorization strategy (`external-oauth2`) applies to all + applications across all Workspaces (Dev Portals) in a {{site.base_gateway}} cluster. + +## Using the {{site.base_gateway}} auth strategy + +If you're using the default `kong-oauth2` authorization strategy with {{site.base_gateway}} as the system of record, set up app registration using the following steps: + +1. Enable the [Application Registration plugin](/gateway/{{page.release}}/kong-enterprise/dev-portal/applications/enable-application-registration/) on a service. + +2. Configure either the [OAuth2](/hub/kong-inc/oauth2/) plugin or the [Key Auth](/hub/kong-inc/key-auth/) plugin on the same service as the Application Registration plugin. + + The OAuth2 plugin can't be used in hybrid mode. + +## Setting external portal authentication {#set-external-oauth2} + +If you are using an external IdP (`external-oauth2`), follow these steps. + +1. Review and choose one of the +[recommended workflows](/gateway/{{page.release}}/kong-enterprise/dev-portal/authentication/3rd-party-oauth#supported-oauth-flows). + +1. Open `kong.conf.default` and set the `portal_app_auth` option to your chosen + strategy. The example configuration below switches from the default + (`kong-oauth2`) to an external IdP (`external-oauth2`). + + ``` + portal_app_auth = external-oauth2 + # Dev Portal application registration + # auth provider and strategy. Must be set to configure + # authentication in conjunction with the application_registration plugin. + # Currently accepts kong-oauth2 or external-oauth2. + ``` + +1. Restart your {{site.base_gateway}} instance. + + ``` + kong reload + ``` + +1. Enable the [Application Registration plugin](/gateway/{{page.release}}/kong-enterprise/dev-portal/applications/enable-application-registration/) on a service. + +1. Configure the [OIDC plugin](/hub/kong-inc/openid-connect/) on the same service as the + Application Registration plugin. + +1. Configure the identity provider for your application, configure your +application in {{site.base_gateway}}, and associate them with each other. See the +[Okta](/gateway/{{page.release}}/kong-enterprise/dev-portal/authentication/okta-config/) +or the [Azure](/gateway/{{page.release}}/kong-enterprise/dev-portal/authentication/azure-oidc-config/) setup examples. diff --git a/app/gateway/2.6.x/developer-portal/administration/application-registration/azure-oidc-config.md b/app/gateway/2.6.x/developer-portal/administration/application-registration/azure-oidc-config.md new file mode 100644 index 000000000000..70762c1770a8 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/administration/application-registration/azure-oidc-config.md @@ -0,0 +1,279 @@ +--- +title: Set Up External Portal Application Authentication with Azure AD and OIDC +badge: enterprise +--- + +These instructions help you set up Azure AD as your third-party identity provider +for use with the Kong OIDC and Portal Application Registration plugins. + +## Prerequisites + +- The `portal_app_auth` configuration option is configured for your OAuth provider + and strategy (`kong-oauth2` or `external-oauth2`). See + [Configure the Authorization Provider Strategy](/gateway/{{page.release}}/developer-portal/administration/application-registration/auth-provider-strategy/) for the Portal Application Registration plugin. + +## Create an Application in Azure + +1. Within Azure, go to the **App registrations** service and register a new application. + + ![Azure App Registrations](/assets/images/products/gateway/dev-portal/ms-azure-app-reg.png) + +1. In **Certificates & secrets**, create a Client secret and save it in a + secure location. You can only view the secret once. + +1. Under **Manifest**, update `accessTokenAcceptedVersion=2` (default is null). + The JSON for your application should look similar to this example: + + ![Azure Manifest](/assets/images/products/gateway/dev-portal/azure-manifest.png) + +## Create a Service in Kong + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -i -X PUT http://localhost:8001/services/httpbin-service-azure \ + --data 'url=https://httpbin.konghq.com/anything' +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http PUT :8001/services/httpbin-service-azure \ + url=https://httpbin.konghq.com/anything +``` +{% endnavtab %} +{% endnavtabs %} + +## Create a Route in Kong + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -i -X PUT http://localhost:8001/services/httpbin-service-azure/routes/httpbin-route-azure \ + --data 'paths=/httpbin-azure' +``` +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http -f PUT :8001/services/httpbin-service-azure/routes/httpbin-route-azure \ + paths=/httpbin-azure +``` + +{% endnavtab %} +{% endnavtabs %} + +## Map the OIDC and Application Registration Plugins to the Service + +Map the OpenID Connect and Application Registration plugins to the **Service**. +The plugins must be applied to a Service to work properly. + +### Step 1: Configure the OIDC plugin for the Service + + +{% navtabs %} +{% navtab Using cURL %} + + ```bash +$ curl -X POST http://localhost:8001/services/httpbin-service-azure/plugins \ + --data name=openid-connect \ + --data config.issuer="https://login.microsoftonline.com//v2.0" \ + --data config.display_errors="true" \ + --data config.client_id="" \ + --data config.client_secret="" \ + --data config.redirect_uri="https://example.com/api" \ + --data config.consumer_claim=aud \ + --data config.scopes="openid" \ + --data config.scopes="YOUR_CLIENT_ID/.default" \ + --data config.verify_parameters="false" +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http -f :8001/services/httpbin-service-azure/plugins \ + name=openid-connect \ + config.issuer=https://login.microsoftonline.com//v2.0 \ + config.display_errors=true \ + config.client_id= \ + config.client_secret="" \ + config.redirect_uri="https://example.com/api" \ + config.consumer_claim=aud \ + config.scopes=openid \ + config.scopes=/.default \ + config.verify_parameters=false +``` +{% endnavtab %} +{% endnavtabs %} + +For more information, see [OIDC plugin](/hub/kong-inc/openid-connect/). + + +### Step 2: Configure the Application Registration plugin for the Service + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -X POST http://localhost:8001/services/httpbin-service-azure/plugins \ + --data "name=application-registration" \ + --data "config.auto_approve=true" \ + --data "config.description=Uses consumer claim with various values (sub, aud, etc.) as registration id to support different flows and use cases." \ + --data "config.display_name=For Azure" \ + --data "config.show_issuer=true" +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http -f :8001/services/httpbin-service-azure/plugins \ + name=application-registration \ + config.auto_approve=true \ + config.display_name="For Azure" \ + config.description="Uses consumer claim with various values (sub, aud, etc.) as registration id to support different flows and use cases." \ + config.show_issuer=true +``` +{% endnavtab %} +{% endnavtabs %} + + +### Step 3: Get an access token from Azure + +Get an access token using the Client Credential workflow and convert the token +into a JSON Web Token (JWT). Replace the placeholder values with your values for +``, ``,``, and +``. + +Get an access token from Azure: + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -X POST https://login.microsoftonline.com//oauth2/v2.0/token \ + --data scope="/.default" \ + --data grant_type="client_credentials" \ + --data client_id="" \ + --data client_secret="" \ +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ https -f POST "https://login.microsoftonline.com//oauth2/v2.0/token" \ + scope=/.default \ + grant_type=client_credentials \ + -a : +``` +{% endnavtab %} +{% endnavtabs %} + +### Step 4: Convert an access token into a JWT token + +1. Paste the access token obtained from the previous step into +[JWT](https://jwt.io). + + ![JWT token converter](/assets/images/products/gateway/dev-portal/jwt-converter.png) + +2. Click **Share JWT** to copy the value for the +[aud (audience)](https://tools.ietf.org/html/rfc7519#section-4.1.3) claim to +your clipboard. You will use the `aud` value as your **Reference ID** in the +next procedure. + +## Create an Application in Kong + +1. Log in to your Dev Portal and create a new application: + 1. Select the **My Apps** menu -> **New Application**. + 2. Enter the **Name** of your Azure application. + 3. Paste the `aud` value generated in JWT in the **Reference ID** field. + 4. (Optional) Enter a **Description**. + + The Create Application form should look similar to this example: + + ![Create Azure Application](/assets/images/products/gateway/dev-portal/azure-app.png) + +2. Click **Create**. + +3. After you create your application, make sure you activate the Service. In the + Services section of the Application Dashboard, click **Activate** on the Service + you want to use. + + The view application details page should look similar to this example: + + ![Azure Example Application](/assets/images/products/gateway/dev-portal/azure-app-details.png) + + Because you enabled + [Auto-approve](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration##aa) + on the associated Application Registration Plugin, an admin won't need to + approve the request. + +## Test your Authentication Flows with your Azure Application + +Follow these instructions to test your client credentials or authorization code +flows with your Azure AD implementation. + +### Test Client Credentials Flow + +#### Step 1: Get a token + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -i -X POST https://:8443/httpbin-azure/oauth2/v2.0/token \ + --data grant_type="client_credentials" \ + --data client_id= \ + --data client_secret= +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ https -f POST "https://:8443/httpbin-azure/oauth2/v2.0/token" \ + scope=/.default \ + grant_type=client_credentials \ + -a : \ + --verify NO +``` +{% endnavtab %} +{% endnavtabs %} + +#### Step 2: Use the token in an authorization header to retrieve the data + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl --header 'Authorization: bearer ' ':8000/httpbin-azure' +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http :8000/httpbin-azure Authorization:'bearer ' +``` +{% endnavtab %} +{% endnavtabs %} + + Replace `` with the bearer token you generated in the previous step. + +### Test Authorization Code Flow + +In your browser, go to `http://localhost:8000/httpbin-azure`. + +You should be guided through a log in process within Azure and then the results +delivered in your browser. + +## Troubleshoot + +If you encounter any issues, review your data plane logs. Because you +enabled `display_errors=true` on the OpenID Connect Plugin, you will receive +more verbose error messages that can help pinpoint any issues. diff --git a/app/gateway/2.6.x/developer-portal/administration/application-registration/enable-application-registration.md b/app/gateway/2.6.x/developer-portal/administration/application-registration/enable-application-registration.md new file mode 100644 index 000000000000..ed3ec5dcf9ca --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/administration/application-registration/enable-application-registration.md @@ -0,0 +1,66 @@ +--- +title: Enable Application Registration +badge: enterprise +--- + +Application registration allows registered developers on the Kong Dev Portal to +authenticate with supported authentication plugins against a service on Kong. +Either {{site.base_gateway}} or external identity provider admins can selectively +admit access to services using Kong Manager. + +## Prerequisites + +* Dev Portal is enabled on the same workspace as the service. +* The service is created and enabled with HTTPS. +* Authentication is enabled on the Dev Portal. +* Logged in as an admin with read and write roles on applications, services, and + developers. +* The `portal_app_auth` configuration option is configured for your OAuth provider + and strategy (`kong-oauth2` default or `external-oauth2`). See +[Configure the Authorization Provider Strategy](/gateway/{{page.release}}/developer-portal/administration/application-registration/auth-provider-strategy/) for the Portal Application Registration plugin. +* Authorization provider configured if using a supported third-party + identity provider with the OIDC plugin: + * For example instructions using Okta as an identity provider, refer to the + [Okta example](/gateway/{{page.release}}/developer-portal/administration/application-registration/okta-config/). + * For example instructions using Azure AD as an identity provider, refer to the + [Azure example](/gateway/{{page.release}}/developer-portal/administration/application-registration/azure-oidc-config/). + +## Enable application registration on a service using Kong Manager {#enable-app-reg-plugin} + +To use application registration on a service, enable the Portal Application Registration +plugin. + +In Kong Manager, access the service for which you want to enable application registration: + +1. From your workspace, in the left navigation pane, go to **API Gateway > Services**. +2. On the Services page, select the service and click **View**. +3. In the Plugins pane in the Services page, click **Add a Plugin**. +4. On the Add New Plugin page in the Authentication section, find the + **Portal Application Registration** plugin and click **Enable**. + +5. Enter the configuration settings. Use the parameters in the next section, + [Application Registration Configuration Parameters](#application-registration-configuration-parameters), + to complete the fields. + + {:.important} + > **Important:** Exposing the Issuer URL is essential for the + [Authorization Code Flow](/gateway/{{page.release}}/developer-portal/administration/application-registration/3rd-party-oauth/#ac-flow) + workflow configured for third-party identity providers. + +6. Click **Create**. + +### Application registration configuration parameters {#app-reg-params} + +| Form Parameter | Description | +|:---------------|:----------------------------------------------------------------------------------| +| `Service` | The service that this plugin configuration will target. Required. | +| `Tags` | A set of strings for grouping and filtering, separated by commas. Optional. | +| `Auto Approve` | If enabled, all new service contract requests are automatically approved. Otherwise, Dev Portal admins must manually approve requests. Default: `false`. | +| `Description` | Description displayed in the information about a service in the Dev Portal. Optional. | +| `Display Name` | Unique name displayed in the information about a service in the Dev Portal. Required. | +| `Show Issuer` | Displays the Issuer URL in the Service Details page. Default: `false`. **Important:** Exposing the **Issuer URL** is essential for the [Authorization Code Flow](/gateway/{{page.release}}/developer-portal/administration/application-registration/3rd-party-oauth/#ac-flow) workflow configured for third-party identity providers. | + +## Next steps + +Choose an [authorization strategy](/gateway/{{page.release}}/developer-portal/administration/application-registration/auth-provider-strategy/) +and configure the appropriate plugin: OAuth2, Key Authentication, or OpenID Connect. diff --git a/app/gateway/2.6.x/developer-portal/administration/application-registration/enable-key-auth-plugin.md b/app/gateway/2.6.x/developer-portal/administration/application-registration/enable-key-auth-plugin.md new file mode 100644 index 000000000000..16219fb7fb73 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/administration/application-registration/enable-key-auth-plugin.md @@ -0,0 +1,138 @@ +--- +title: Enable Key Authentication for Application Registration +badge: enterprise +--- + +You can use the Key Authentication plugin for authentication in conjunction with +the Application Registration plugin. + +The key auth plugin uses the same Client ID as generated for the Kong OAuth2 plugin. +You can use the same Client ID credential for a Service that has the OAuth2 plugin enabled. + +## Prerequisites + +* {{site.ee_product_name}} is installed, version 2.2.1.0 or later. +* Create a Service. +* Enable the [Application Registration plugin](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration/) on a Service. +* Activate your application for a Service if you have not already done so. The +Service Contract must be approved by an Admin if auto approve is not enabled. +* [Generate a credential](#gen-client-id-cred) if you don't want to use the default credential initially created for you. + +## Enable Key Authentication in Kong Manager + +In Kong Manager, access the Service for which you want to enable key authentication for +use with application registration: + +1. From your Workspace, in the left navigation pane, go to **API Gateway > Services**. +2. On the Services page, select the Service and click **View**. +3. In the Plugins pane in the Services page, click **Add a Plugin**. +4. On the Add New Plugin page in the Authentication section, find the + **Key Authentication** Plugin and click **Enable**. + + ![Key Authentication plugin panel](/assets/images/products/gateway/dev-portal/key-auth-plugin-panel.png) + +5. Complete the fields as appropriate for your application. In this example, the Service is already + prepopulated. Refer to the parameters described in the next section, + [Key Authentication Configuration Parameters](#key-auth-params), + to complete the fields. + +6. Click **Create**. + +### Key Authentication Configuration Parameters {#key-auth-params} + +| Form Parameter | Description | +|:---------------|:----------------------------------------------------------------------------------| +| `Service` | The Service that this plugin configuration will target. Required. | +| `Anonymous` | An optional string (Consumer UUID) value to use as an anonymous Consumer if authentication fails. If empty (default), the request fails with an `4xx`. Note that this value must refer to the Consumer `id` attribute that is internal to Kong, and **not** its `custom_id`. | +| `Hide Credentials` | Whether to show or hide the credential from the Upstream service. If `true`, the plugin strips the credential from the request (i.e., the header, query string, or request body containing the key) before proxying it. Default: `false`. | +| `Key in Body` | If enabled, the plugin reads the request body (if said request has one and its MIME type is supported) and tries to find the key in it. Supported MIME types: `application/www-form-urlencoded`, `application/json`, and `multipart/form-data`. Default: `false`. | +| `Key in Header` | If enabled (default), the plugin reads the request header and tries to find the key in it. Default: true. | +| `Key in Query` | If enabled (default), the plugin reads the query parameter in the request and tries to find the key in it. Default: true. | +| `Key Names` | Describes an array of parameter names where the plugin will look for a key. The client must send the authentication key in one of those key names, and the plugin will try to read the credential from a header, request body, or query string parameter with the same name. The key names may only contain [a-z], [A-Z], [0-9], [_] underscore, and [-] hyphen. Required. Default: `apikey`. | +| `Run on Preflight` | Indicates whether the plugin should run (and try to authenticate) on `OPTIONS` preflight requests. Default: `true`. | + +## Generate a Credential {#gen-client-id-cred} + +Generate a Client ID credential to use as an API key. You can generate multiple +credentials. + +1. In the **Dev Portal > My Apps** page, click **View** for an application. + +2. In the **Authentication** pane, click **Generate Credential**. + + ![Application Authentication Pane](/assets/images/products/gateway/dev-portal/gen-client-id-secret.png) + + Now you can make requests using the Client ID as an API Key. + +## Make Requests with an API Key (Client Identifier) + +The Client ID of your credentials can be used as an API key to make authenticated requests to a Service. + +**Tip:** You can also access key request instructions directly within the user interface from the +information icon in the Services details area of your application. Click the **i** icon to open the Service Details page. + +![Services Pane](/assets/images/products/gateway/dev-portal/portal-info-modal-key-auth.png) + +Scroll to view all of the available examples. + +![Service Details Page Embedded Key Usage Instructions](/assets/images/products/gateway/dev-portal/service-details-key-auth-usage.png) + +### About API Key Locations in a Request + +{% include /md/plugins-hub/api-key-locations.md %} + +### Make a request with the key as a query string parameter + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +$ curl -X POST {proxy}/{route}?apikey={CLIENT_ID} +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +$ http {proxy}/{route}?apikey={CLIENT_ID} +``` +{% endnavtab %} +{% endnavtabs %} + +Response (will be the same for all valid requests regardless of key location): + +```bash +HTTP/1.1 200 OK +... +``` + +### Make a request with the key in a header + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +$ curl -X POST {proxy}/{route} \ +--header "apikey: {CLIENT_ID}" +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +$ http {proxy}/{route} apikey:{CLIENT_ID} +``` +{% endnavtab %} +{% endnavtabs %} + +### Make a request with the key in the body + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +$ curl -X POST {proxy}/{route} \ +--data "apikey:={CLIENT_ID}" +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +$ http {proxy}/{route} apikey={CLIENT_ID} +``` +{% endnavtab %} +{% endnavtabs %} + +**Note:** The `key_in_body` parameter must be set to `true`. diff --git a/app/gateway/2.6.x/developer-portal/administration/application-registration/managing-applications.md b/app/gateway/2.6.x/developer-portal/administration/application-registration/managing-applications.md new file mode 100644 index 000000000000..c66adb37ed2c --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/administration/application-registration/managing-applications.md @@ -0,0 +1,58 @@ +--- +title: Manage Applications +badge: enterprise +--- + +Developers can create applications from the Kong Dev Portal. An application can apply to any number of Services. This is called a Service Contract. To use an application with a Service, the Service Contract must have an Approved status. To enable automatic approval for all new Service Contracts, enable Auto-approve for the Portal Application Registration plugin. + +## Create an Application + +1. Log in to the Kong Dev Portal. +2. Click **My Apps** in the top navigation bar. +3. Click **New Application**. +4. Complete the **Create Application** dialog: + 1. Enter a unique `Application Name`. + 2. Enter a `Redirect URI`. + 3. Enter a `Description`. +5. Click **Create**. The Application Dashboard is displayed. From the +dashboard, you can view details about your application, view your credentials, +generate more credentials, and view your application status against a list of +Services. +6. Before you can use your application, you must activate it to create a Service +Contract for the Service. In the Services section of the Application Dashboard, +click **Activate** on the Service you want to use. If [Auto-approve](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration##aa) is not +enabled, your application will remain pending until an admin approves your +request. + +## View all Service Contracts for an Application + +A list of all applications in a Workspace can be accessed from the left navigation pane. + +1. Click **Applications** to view the list of applications. +2. From the Applications list, click an application to view all Service Contracts for the application; including contracts in Approved, Revoked, and Rejected status. +3. In the Service Contracts section, click the **Requested Access** tab to view Service Contracts requests for the application. Approve, revoke, or reject +requests. + +## View all Application Contracts for a Service + +View all Application Contracts and their status for a Service from the +**Service** page. + +1. Click **Services** in the left navigation pane. +2. Select the Service for which you have Application Registration enabled. +3. From the Service Contracts tab, view all Approved, Revoked, Rejected, and Requested Access for the Service. + +## Add a Document to your Service +When using Application Registration, it is recommended to link documentation +(OAS/Swagger spec) to your Service. Doing so allows Dev Portal users to easily +register Application Contracts for their applications from the documentation +page, and view a list of all documentation from the Catalog page. + +Add a document from the Service **View** page: +1. From your Workspace, in the left navigation pane, go to **API Gateway > Services**. +2. On the Services page, select the Service for which you want to add a document and click **View**. +3. In the Documents section, click **Add a Document**. +4. Choose a method to add the document to the Service: + - Use **Document Spec Path** to select an existing spec in the Portal. + - Use **Upload Document** to upload a new spec to the Portal. +5. Click **Add Document**. diff --git a/app/gateway/2.6.x/developer-portal/administration/application-registration/okta-config.md b/app/gateway/2.6.x/developer-portal/administration/application-registration/okta-config.md new file mode 100644 index 000000000000..7e5dd61f3426 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/administration/application-registration/okta-config.md @@ -0,0 +1,120 @@ +--- +title: Set Up External Portal Application Authentication with Okta and OIDC +badge: enterprise +--- + +These instructions help you set up Okta as your third-party identity provider +for use with the Kong OIDC and Portal Application Registration plugins. + +## Define an authorization server and create a custom claim in Okta {#auth-server-cclaim} + +Follow these steps to set up an authorization server in Okta for all authorization types. + +1. Sign in to the [Developer Okta site](https://developer.okta.com/). +2. Click **API > Authorization Servers**. + + ![Okta Authorization Server](/assets/images/products/gateway/dev-portal/okta-api-auth-server.png) + + Notice that you already have an authorization server set up named `default`. + This example uses the default auth server. You can also create as many + custom authorization servers as necessary to fulfill your requirements. For + more information, refer to the + [Okta developer documentation](https://developer.okta.com/docs/guides/customize-authz-server/overview/). + +3. Click **default** to view the details for the default auth server. Take note +of the `Issuer` URL, which you will use to associate Kong with your authorization server. + + ![Okta Issuer URL](/assets/images/products/gateway/dev-portal/okta-auth-server-issuer-url.png) + +4. Click the **Claims** tab. + + ![Okta Issuer URL](/assets/images/products/gateway/dev-portal/okta-auth-server-claims.png) + +5. Click **Add Claim**. Add a custom claim called `application_id` that will attach any successfully authenticated application's `id` to the access token. + 1. Enter `application_id` in the **Name** field. + 2. Ensure the `Include in token type` selection is **Access Token**. + 3. Enter `app.clientId` in the **Value** field. + 4. Click **Create**. + + ![Okta Claim](/assets/images/products/gateway/dev-portal/okta-add-claim.png) + + Now that you have created a custom claim, you can associate the `client_id` + with a Service via the Application Registration plugin. Start by creating a Service in Kong Manager. + +7. Create a Service and a Route and instantiate an OIDC plugin on that Service. + You can allow most options to use their defaults. + + 1. In the `Config.Issuer` field, enter the Issuer URL of the Authorization server from your identity provider. + + ![OIDC with Okta Issuer URL](/assets/images/products/gateway/dev-portal/oidc-issuer-url.png) + + 2. In the `Config.Consumer Claim` field, enter the name of the field from the Okta payload that contains the application ID. + This is usually `sub`. + + **Tip:** Because Okta's discovery document does not include all supported + auth types by default, ensure the + `config.verify_parameters` option is disabled. + + ![Clear Config Verify Parameters for OIDC with Okta](/assets/images/products/gateway/dev-portal/oidc-clear-verify-params-app-reg.png) + + The core configuration should be: + + ```json + { + "issuer": "", + "verify_credentials": false, + "consumer_claim": "sub", + } + + ``` + +8. Configure a Portal Application Registration plugin on the Service as well. See +[Application Registration](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration#config-app-reg-plugin). + +## Register an application in Okta + +Follow these steps to register an application in Okta and associate the Okta +application with an application in the Kong Dev Portal. + +1. Sign in to the [Developer Okta site](https://developer.okta.com/). +2. Click **Applications** > **+ Add Application**. +3. Depending on which authentication flow you want to implement, the setup of +your Okta application will vary: + + - **Client Credentials**: Select `Machine-to-Machine` when prompted for an application type. + + ![Okta Create New Application](/assets/images/products/gateway/dev-portal/okta-client-creds-app.png) + + You will need your `client_id` and `client_secret` later on when you [authenticate with the proxy](/gateway/{{page.release}}/developer-portal/administration/application-registration/3rd-party-oauth#cc-flow). + + ![Okta Client Credentials](/assets/images/products/gateway/dev-portal/okta-client-id-secret.png) + + - **Implicit Grant**: Select `Single-Page App`, `Native`, or `Web` when + prompted for an application type. Make sure `Implicit` is selected for + `Allowed grant types`. Enter the `Login redirect URIs`, `Logout redirect URIs`, and `Initiate login URI` fields with the correct values, depending on your application's routing. The Implicit Grant flow is not recommended if the Authorization Code flow is possible. + + - **Authorization Code**: Select `Single-Page App`, `Native`, or `Web` when + prompted for an application type. Make sure `Authorization Code` is selected for `Allowed grant types`. Enter the `Login redirect URIs`, `Logout redirect URIs`, and `Initiate login URI` fields with the correct values, depending on your application's routing. + +## Associate the identity provider application with your Kong application + +Now that the application has been configured in Okta, you need to associate the +Okta application with the corresponding application in Kong's Dev Portal. + +{:.note} +> **Note:** Each developer should have their own application in both Okta and Kong. +Each Okta application has its own `client_id` that maps to its respective application in Kong. +Essentially, this maps identity provider applications to portal applications. + +This example assumes Client Credentials is the chosen OAuth flow. + +1. In the Kong Dev Portal, create an account if you haven't already. +2. After you've logged in, click `My Apps`. +3. On the Applications page, click `+ New Application`. +4. Complete the **Name** and **Description** fields. Paste the `client_id` of your corresponding Okta (or other identity provider) application into the **Reference Id** field. + + ![Kong Create Application with Reference Id](/assets/images/products/gateway/dev-portal/create-app-ref-id.png) + +Now that the application has been created, developers can authenticate with the +endpoint using the supported and recommended +[third-party OAuth flows](/gateway/{{page.release}}/developer-portal/administration/application-registration/3rd-party-oauth). diff --git a/app/gateway/2.6.x/developer-portal/administration/developer-permissions.md b/app/gateway/2.6.x/developer-portal/administration/developer-permissions.md new file mode 100644 index 000000000000..bbd41e4dd296 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/administration/developer-permissions.md @@ -0,0 +1,87 @@ +--- +title: Developer Roles and Content Permissions +badge: enterprise +--- + +Access to the Dev Portal can be fine-tuned with the use of Developer +Roles and Content Permissions, managed through the Dev Portal Permissions page +of Kong Manager. This page can be found by clicking the **Permissions** link +under **Dev Portal** in the Kong Manager navigation bar. + +## Roles + +The Roles Tab contains a list of available developer roles as well as providing +the ability to create and edit roles. + +Selecting Create Role allows you to enter a unique role name, as well as a +comment to provide context for the nature of the role. You can assign the role +to existing developers from within the role creation page. Clicking Create +saves the role and returns you to the Roles List view. There you can see your +newly created role as well as any other previously defined roles. + +Clicking View displays the Role Details page with a list of developers assigned. + +From the Role Details page, click the Edit button to make changes to the role. You can also access this page from the Roles List Edit button. Here you can change the name and comment of the role, assign or remove developers, or delete the role. + +Deleting a role will remove it from any developers assigned the role and remove +the role restriction from any content files it is applied to. + +## Content + +The Content Tab shows the list of content files used by the Dev Portal. You can +apply roles to your content files, restricting access only to developers who +possess certain roles. Selecting an individual content file displays a +dropdown of available developer roles where you can choose which role has +access to the file. Unchecking all available roles will leave the file +unauthenticated. + +An additional option, the `*` role, is preset in the list. This predefined role +behaves differently from other roles. When a content file has the `*` role +attached to it, any developer may view the page as long as they are +authenticated. Additionally, the `*` role may not be used in conjunction with +other user-defined roles and will deselect those roles when `*` is selected. + +{:.important} +> **Important:** The `dashboard.txt` and `settings.txt` content files are +assigned the `*` role by default. All other content files have no roles by +default. This means that until a role is added, the file is unauthenticated +even if Dev Portal Authentication is enabled. Content Permissions are ignored +when Dev Portal Authentication is disabled. + +## `readable_by` attribute + +When a role is applied to a content file using the Content Tab, a special +attribute `readable_by` is added to the headmatter of the file. + +``` +--- +readable_by: + - role_name + - another_role_name +--- +``` + + In the case of spec files, `readable_by` is applied under the key `x-headmatter` or `X-headmatter`. + +``` +x-headmatter: + readable_by: + - role_name + - another_role_name +``` + +The value of `readable_by` is an array of string role names that have access to +view the content file. An exception is when the `*` role is applied to the +file. In this case, the value of `readable_by` is no longer an array, because +it contains the single string character `*`. + +``` +readable_by: "*" +``` + +⚠️**Important:** If you manually remove or edit the `readable_by` attribute, it +will modify the permissions of the file. Attempting to save a content file with +a `readable_by` array containing a nonexistent role name will result in an +error. Additionally, if you make changes to permissions in the Content Tab or +the Portal Editor, be sure to sync any local files so that permissions are not +overwritten the next time you push changes. diff --git a/app/gateway/2.6.x/developer-portal/administration/managing-developers.md b/app/gateway/2.6.x/developer-portal/administration/managing-developers.md new file mode 100644 index 000000000000..2928da004653 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/administration/managing-developers.md @@ -0,0 +1,148 @@ +--- +title: Managing Developers +badge: enterprise +--- + +## Developer Status + +A status represents the state of a developer and the access they have to the Dev + Portal and APIs: + +* **Approved** + * A developer who can access the Dev Portal. Approved developers can create + credentials & access **all** APIs that allow those credentials. +* **Requested** + * A developer who has requested access but has not yet been Approved. +* **Rejected** + * A developer who has had their request denied by a Kong admin. +* **Revoked** + * A developer who once had access to the Dev Portal but has since had access + Revoked. + + +![Managing Developers](https://konghq.com/wp-content/uploads/2018/05/gui-developer-tabs.png) + +## Approving Developers + +Developers who have requested access to a Dev Portal will appear under the +**Requested Access** tab. From this tab, you can choose to *Accept* or *Reject* +the developer from the actions in the table row. After selecting an action, the +corresponding tab is updated. + + +## View Approved Developers + +To view all currently approved developers, click the **Approved** tab. From here, you can choose to *Revoke* or *Delete* a particular developer. Additionally, you can use this view to send an email to a developer with the **Email Developer** `mailto` link. See [Emailing Developers](#emailing-developers) for more info. + + +## View Revoked Developers + +To view all currently revoked developers, click the **Revoked** tab. From here, you can choose to *Re-approve* or *Delete* a developer. + + +### View Rejected Developers + +To view all currently rejected developers, click the **Rejected** tab. Rejected developers completed the registration flow on your Dev Portal but were rejected from the **Request Access** tab. You may *Approve* or *Delete* a developer from this tab. + + +## Email Developers + +### Invite Developers to Register + +To invite a single or multiple developers: + +1. Click **Invite Developers**. +2. Use the popup modal to enter email addresses separated by commas. +3. After all emails have been added, click **Invite**. A pre-filled message +opens in your default email client with a link to the registration page for +your Dev Portal. + +Each developer is bcc'd by default for privacy. You may choose to edit the message or send as is. + +![Invite Developers](https://konghq.com/wp-content/uploads/2018/05/invite-developers.png) + + +## Developer Management Property Reference + + + +### portal_auto_approve + +**Default:** `off` + +**Description:** +Dev Portal Auto Approve Access. + +When set to `on`, a developer will automatically be marked as `approved` after +completing Dev Portal registration. Access can still be revoked through +Kong Manager or the API. + +When set to `off`, a Kong admin will have to manually approve the Developer +using Kong Manager or the API. + + +### portal_invite_email + +**Default:** `on` + +**Description:** +When enabled, Kong admins can invite developers to a Dev Portal by using +the Invite button in Kong Manager. + + +### portal_access_request_email + +**Default:** `on` + +**Description:** +When enabled, Kong admins specified by `smtp_admin_emails` will receive an email +when a developer requests access to a Dev Portal. + +When disabled, Kong admins will have to manually check the Kong Manager to view +any requests. + + +### portal_approved_email + +**Default:** `on` + +**Description:** +When enabled, developers will receive an email when access to a Dev Portal has +been approved. + +When disabled, developers will receive no indication that they have been +approved. It is suggested to only disable this feature if `portal_auto_approve` +is enabled. + + +### portal_reset_email + +**Default:** `on` + +**Description:** +When enabled, developers will be able to use the Reset Password flow on a Dev +Portal and will receive an email with password reset instructions. + +When disabled, developers will *not* be able to reset their account passwords. +Kong Admins will have to manually create new credentials for the Developer in +the Kong Manager. + +### portal_token_exp + +**Default:** `21600` + +**Description:** +Duration in seconds for the expiration of the Dev Portal reset password token. +Default is `21600` (six hours). + + +### portal_reset_success_email + +**Default:** `on` + +**Description:** +When enabled, developers will receive an email after successfully resetting +their Dev Portal account password. + +When disabled, developers will still be able to reset their account passwords, +but will not receive a confirmation email. diff --git a/app/gateway/2.6.x/developer-portal/configuration/authentication/adding-registration-fields.md b/app/gateway/2.6.x/developer-portal/configuration/authentication/adding-registration-fields.md new file mode 100644 index 000000000000..9488632184f0 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/configuration/authentication/adding-registration-fields.md @@ -0,0 +1,24 @@ +--- +title: Adding Dev Portal Registration Fields +badge: enterprise +--- + +When authentication is enabled for a Dev Portal, the only required +fields by default are **full name**, **email**, and **password**. However, you +can add custom fields to this form and indicate whether the fields are +required. Adding custom required fields will not affect existing registered +users until they choose to edit their profile. + +### Adding Custom Registration Fields + +1. In Kong Manager, navigate to the Workspace's Dev Portal **Settings** page. + +2. Click the **Developer Meta Fields** tab. + +3. Click **+ Add Field** to add a new field object to the form. + +4. Enter a label, field name, and select the type of input. + +5. Select the **Required** checkbox to require the new field for registration. + +6. Click **Save Changes**. The field is automatically added to the registration form. diff --git a/app/gateway/2.6.x/developer-portal/configuration/authentication/basic-auth.md b/app/gateway/2.6.x/developer-portal/configuration/authentication/basic-auth.md new file mode 100644 index 000000000000..f877716c2149 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/configuration/authentication/basic-auth.md @@ -0,0 +1,84 @@ +--- +title: Enable Basic Auth in the Dev Portal +badge: enterprise +--- + +The Kong Dev Portal can be fully or partially authenticated using HTTP protocol's Basic Authentication scheme. Requests are sent with an Authorization header that +contains the word `Basic` followed by the base64-encoded `username:password` string. + +Basic Authentication for the Dev Portal can be enabled using any of the following ways: + +- [Kong Manager](#enable-basic-auth-using-kong-manager) +- [Command line](#enable-basic-auth-using-the-command-line) +- [Kong configuration file](#enable-basic-auth-using-kongconf) + +**Warnings:** + +- Enabling authentication in the Dev Portal requires use of the +Sessions plugin. Developers will not be able to log in if this is not properly set. +For more information, see +[Sessions in the Dev Portal](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions). + +- When Dev Portal Authentication is enabled, content files remain unauthenticated until a role is applied to them. The exceptions are `settings.txt` and `dashboard.txt`, which begin with the `*` role. For more information, see +[Developer Roles and Content Permissions](/gateway/{{page.release}}/developer-portal/administration/developer-permissions). + + +## Enable Portal Session Config + +In the Kong configuration file, set the `portal_session_conf` property: + +``` +portal_session_conf={ "cookie_name":"portal_session","secret":"","storage":"kong"} +``` + +If using HTTP while testing, include `"cookie_secure": false` in the config: + +``` +portal_session_conf={ "cookie_name":"portal_session","secret":"","storage":"kong","cookie_secure":false} +``` + +Or, if you have different subdomains for the `portal_api_url` and `portal_gui_host`, set the `cookie_domain` +and `cookie_samesite` properties as follows: + +``` +portal_session_conf={ "cookie_name":"portal_session","secret":"","storage":"kong","cookie_secure":false,"cookie_domain":"<.your_subdomain.com>","cookie_samesite":"off" } +``` + +### See Also + +- For more information about portal session configuration, see +[Sessions](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions#portal-session-conf). + +- For more information about domains and cookies in Dev Portal sessions, see +[Domains](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions#domains). + +## Enable Basic Auth Using Kong Manager + +1. Navigate to the Dev Portal's **Settings** page. +2. Find **Authentication plugin** under the **Authentication** tab. +3. Select **Basic Authentication**. +4. Click **Save Changes**. + +![Authentication plugin](/assets/images/products/gateway/dev-portal/portal-settings-auth-plugin.png) + +## Enable Basic Auth Using the Command Line + +To patch a Dev Portal's authentication property directly, run: + +```bash +$ curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal_auth=basic-auth" +``` + +## Enable Basic Auth Using `kong.conf` + +Kong allows for a default authentication plugin to be set in the Kong +configuration file with the `portal_auth` property. + +In your `kong.conf` file, set the property as follows: + +``` +portal_auth="basic-auth" +``` + +This sets all Dev Portals to use Basic Authentication by default when initialized. diff --git a/app/gateway/2.6.x/developer-portal/configuration/authentication/key-auth.md b/app/gateway/2.6.x/developer-portal/configuration/authentication/key-auth.md new file mode 100644 index 000000000000..dd68c2b7940b --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/configuration/authentication/key-auth.md @@ -0,0 +1,64 @@ +--- +title: Enable Key Auth in the Dev Portal +badge: enterprise +--- + +The Kong Dev Portal can be fully or partially authenticated using API keys or **Key +Authentication**. Users provide a unique key upon registering and use this key +to log into the Dev Portal. + +Key Authentication for the Dev Portal can be enabled in three ways: + +- via the [Kong Manager](#enable-key-auth-via-kong-manager) +- via the [command line](#enable-key-auth-via-the-command-line) +- via the [Kong configuration file](#enable-key-auth-via-the-kongconf) + +>**Warning** Enabling authentication in the Dev Portal requires use of the +> Sessions plugin. Developers will not be able to login if this is not set +> properly. More information about [Sessions in the Dev Portal](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions/) + +## Enable Portal Session Config + +``` +portal_session_conf={ "cookie_name": "portal_session", "secret": "CHANGE_THIS", "storage": "kong" } +``` + +If using HTTP while testing, include `"cookie_secure": false` in the config: + +``` +portal_session_conf={ "cookie_name": "portal_session", "secret": "CHANGE_THIS", "storage": "kong", "cookie_secure": false } +``` + +## Enable Key Auth via Kong Manager + +1. Navigate to the Dev Portal's **Settings** page. +2. Find **Authentication plugin** under the **Authentication** tab. +3. Select **Key Authentication** from the drop down. +4. Click **Save Changes**. + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +## Enable Key Auth via the Command Line + +To patch a Dev Portal's authentication property directly, run: + +``` +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal_auth=key-auth" +``` + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +## Enable Key Auth via the Kong.conf + +Kong allows for a `default authentication plugin` to be set in the Kong +configuration file with the `portal_auth` property. + +In your `kong.conf` file, set the property as follows: + +``` +portal_auth="key-auth" +``` + +This will set every Dev Portal to use Key Authentication by default when +initialized, regardless of Workspace. diff --git a/app/gateway/2.6.x/developer-portal/configuration/authentication/oidc.md b/app/gateway/2.6.x/developer-portal/configuration/authentication/oidc.md new file mode 100644 index 000000000000..7989fcb27748 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/configuration/authentication/oidc.md @@ -0,0 +1,138 @@ +--- +title: Enable OpenID Connect in the Dev Portal +badge: enterprise +--- + +The [OpenID Connect Plugin](/hub/kong-inc/openid-connect/) (OIDC) +allows the Kong Dev Portal to hook into existing authentication setups using third-party +*Identity Providers* (IdP) such as Google, Okta, Microsoft Azure AD, +[Curity](/gateway/{{page.release}}/configure/auth/oidc-curity/#kong-dev-portal-authentication), etc. + +[OIDC](/hub/kong-inc/openid-connect/) must be used with +the `session` method, utilizing cookies for Dev Portal File API requests. + +In addition, a configuration object is required to enable OIDC. Refer to the +[Sample Configuration Object](#/sample-configuration-object) section of this +document for more information. + +**Note:** The Dev Portal does not automatically create developer accounts on login via OIDC. +A developer account matching the `consumer_claim` configuration parameter has to be +created and approved (if auto approve is not enabled) beforehand. + +OIDC for the Dev Portal can be enabled in one of the following ways: + +- [Kong Manager](#enable-oidc-using-kong-manager) +- [Kong Admin API (command line)](#enable-oidc-using-the-command-line) +- [The Kong configuration file](#enable-oidc-using-kongconf) + + +## Portal Session Plugin Config + +Session Plugin Config does not apply when using OpenID Connect. + +## Sample Configuration Object + +Below is a sample configuration JSON object for using *Google* as the Identity +Provider: + +``` +{ + "consumer_by": ["username","custom_id","id"], + "leeway": 1000, + "scopes": ["openid","profile","email","offline_access"], + "logout_query_arg": "logout", + "client_id": [""], + "login_action": "redirect", + "logout_redirect_uri": ["http://localhost:8003"], + "ssl_verify": false, + "consumer_claim": ["email"], + "forbidden_redirect_uri": ["http://localhost:8003/unauthorized"], + "client_secret": [""], + "issuer": "https://accounts.google.com/", + "logout_methods": ["GET"], + "login_redirect_uri": ["http://localhost:8003"], + "login_redirect_mode": "query" +} +``` + +The placeholders above should be replaced with your actual values: + + - `` - Client ID provided by IdP + - `` - Client secret provided by IdP + +See the [documentation of the OpenID Connect plugin](/hub/kong-inc/openid-connect/) +for more information. + +**Important:** The `redirect_uri` needs to be configured as an allowed URI in the IdP. +If not set explicitly in the configuration object, the URI default is +`http://localhost:8004//auth`. + +If `portal_gui_host` and `portal_api_url` are set to share a domain but differ +with regard to subdomain, `redirect_uri` and `session_cookie_domain` need to be +configured to allow OpenID Connect to apply the session correctly. + +Example: + +``` +{ + "consumer_by": ["username","custom_id","id"], + "leeway": 1000, + "scopes": ["openid","profile","email","offline_access"], + "logout_query_arg": "logout", + "client_id": [""], + "login_redirect_uri": ["https://example.portal.com"], + "login_action": "redirect", + "logout_redirect_uri": ["https://example.portal.com"], + "ssl_verify": false, + "consumer_claim": ["email"], + "redirect_uri": ["https://exampleapi.portal.com/auth"], + "session_cookie_domain": ".portal.com", + "forbidden_redirect_uri": ["https://example.portal.com/unauthorized"], + "client_secret": ["**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +## Enable OIDC using the Command Line + +You can use the Kong Admin API to set up Dev Portal Authentication. +To patch a Dev Portal's authentication property directly, run: + +``` +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal_auth=openid-connect" + "config.portal_auth_conf= +``` + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +## Enable OIDC using kong.conf + +Kong allows for a `default authentication plugin` to be set in the Kong +configuration file with the `portal_auth` property. + +In your `kong.conf` file, set the property as follows: + +``` +portal_auth="openid-connect" +``` + +Then set the `portal_auth_conf` property to your +customized [**Configuration JSON Object**](#sample-configuration-object). + +This will set every Dev Portal to use OIDC by default when initialized, regardless of Workspace. diff --git a/app/gateway/2.6.x/developer-portal/configuration/authentication/sessions.md b/app/gateway/2.6.x/developer-portal/configuration/authentication/sessions.md new file mode 100644 index 000000000000..3d7e4260006d --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/configuration/authentication/sessions.md @@ -0,0 +1,116 @@ +--- +title: Sessions in the Dev Portal +--- + +{:.important} +> **Important**: Portal Session Configuration does not apply when using [OpenID Connect](/hub/kong-inc/openid-connect/) for Dev Portal authentication. The following information assumes that the Dev Portal is configured with `portal_auth` other than `openid-connect`; for example, `key-auth` or `basic-auth`. + +## How does the Sessions Plugin work in the Dev Portal? + +When a user logs in to the Dev Portal with their credentials, the Sessions Plugin will create a session cookie. The cookie is used for all subsequent requests and is valid to authenticate the user. The session has a limited duration and renews at a configurable interval, which helps prevent an attacker from obtaining and using a stale cookie after the session has ended. + +The Session configuration is secure by default, which may [require alteration](#session-security) if using HTTP or different domains for [`portal_api_url`](/gateway/{{page.release}}/reference/configuration/#portal_api_url) and [`portal_gui_host`](/gateway/{{page.release}}/reference/configuration/#portal_gui_host). Even if an attacker were to obtain a stale cookie, it would not benefit them since the cookie is encrypted. The encrypted session data may be stored either in Kong or the cookie itself. + +## Configuration to Use the Sessions Plugin with the Dev Portal + +To enable sessions authentication, configure the following: + +``` +portal_auth = +portal_session_conf = { + "secret":"", + "cookie_name":"", + "storage":"kong", + "cookie_lifetime":, + "cookie_renew":, + "cookie_secure":, + "cookie_domain":"", + "cookie_samesite":"" +} +``` + +* `"cookie_name":""`: The name of the cookie + * For example, `"cookie_name":"portal_cookie"` +* `"secret":""`: The secret used in keyed HMAC generation. Although + the **Session Plugin's** default is a random string, the `secret` _must_ be + manually set for use with the Dev Portal since it must be the same across all + Kong workers/nodes. +* `"storage":"kong"`: Where session data is stored. This value _must_ be set to `kong` for use with the Dev Portal. +* `"cookie_lifetime":`: The duration (in seconds) that the session will remain open; 3600 by default. +* `"cookie_renew":`: The duration (in seconds) of a session remaining at which point + the Plugin renews the session; 600 by default. +* `"cookie_secure":`: `true` by default. See [Session Security](#session-security) for + exceptions. +* `"cookie_domain"::` Optional. See [Session Security](#session-security) for exceptions. +* `"cookie_samesite":""`: `"Strict"` by default. See [Session Security](#session-security) for + exceptions. + +⚠️**Important:** +*The following properties must not be altered from default for use with the Dev Portal:* +* `logout_methods` +* `logout_query_arg` +* `logout_post_arg` + +For detailed descriptions of each configuration property, see the [Session Plugin documentation](/hub/kong-inc/session/). + +## Session Security + +The Session configuration is secure by default, so the cookie uses the [Secure, HttpOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies), and [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies) directives. + +⚠️**Important:** The following properties must be altered depending on the protocol and domains in use: +* If using HTTP instead of HTTPS: `"cookie_secure": false` +* If using different subdomains for the [`portal_api_url`](/gateway/{{page.release}}/reference/configuration/#portal_api_url) and [`portal_gui_host`](/gateway/{{page.release}}/reference/configuration/#portal_gui_host), see the example below for [Domains](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions/#domains). + +{:.important} +> **Important:** Sessions are not invalidated when a user logs out if `"storage": "cookie"` +(the default) is used. In that case, the cookie is deleted client-side. Only when session data is +stored server-side with `"storage": "kong"` set is the session actively invalidated. + +## Example Configurations + +### HTTPS with the same domain for API and GUI + +If using HTTPS and hosting Dev Portal API and the Dev Portal GUI from the same domain, the following configuration could be used for Basic Auth: + +``` +portal_auth = basic-auth +portal_session_conf = { + "cookie_name":"$4m04$" + "secret":"change-this-secret" + "storage":"kong" + "cookie_secure":true +} +``` + +In testing, if using HTTP, the following configuration could be used instead: + +``` +portal_auth = basic-auth +portal_session_conf = { + "cookie_name":"04tm34l" + "secret":"change-this-secret" + "storage":"kong" + "cookie_secure":false +} +``` + +### Domains + +The dev portal `portal_gui_host` and the dev +portal api `portal_api_url` must share a domain or subdomain. The following +example assumes subdomains of `portal.xyz.com` and `portalapi.xyz.com`. +Set a subdomain such as ``"cookie_domain": ".xyz.com"`` and set +`cookie_samesite` to `off`. + +``` +portal_auth = basic-auth +portal_session_conf = { + "storage":"kong" + "cookie_name":"portal_session" + "cookie_domain": ".xyz.com" + "secret":"super-secret" + "cookie_secure":false + "cookie_lifetime":31557600, + "cookie_samesite":"off" +} +``` diff --git a/app/gateway/2.6.x/developer-portal/configuration/smtp.md b/app/gateway/2.6.x/developer-portal/configuration/smtp.md new file mode 100644 index 000000000000..7647111fae51 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/configuration/smtp.md @@ -0,0 +1,152 @@ +--- +title: Dev Portal SMTP Configuration +badge: enterprise +--- + +The following property reference outlines each email and email variable used by the Dev Portal to send emails to Kong admins and developers. + +These settings can be modified in the `Kong Manager` under the Dev Portal `Settings / Email` tab, or by running the following command: + +``` +curl http://localhost:8001/workspaces/ \ + --data "config.=off" +``` + +If they are not modified manually, the Dev Portal will use the default value defined in the Kong Configuration file. + +In 1.3.0.1 or greater, [Dev Portal email content and styling can be customized via template files](/gateway/{{page.release}}/developer-portal/theme-customization/emails/) + + + + +## portal_invite_email + +**Default:** `on` + +**Description:** +When enabled, Kong admins will be able to invite developers to a Dev Portal by using the Invite button in the Kong Manager. + +**Email:** +``` +Subject: Invite to access Dev Portal + +Hello Developer! + +You have been invited to create a Dev Portal account at %s. +Please visit `` to create your account. +``` + + +## portal_email_verification + +**Default:** `off` + +**Description:** +When enabled, developers will receive an email upon registration to verify their account. Developers will not be able to use the Dev Portal until their account is verified, even if auto-approve is enabled. + + +## portal_access_request_email + +**Default:** `on` + +**Description:** +When enabled, Kong Admins specified by `smtp_admin_emails` will receive an email when a Developer requests access to a Dev Portal. + +``` +Subject: Request to access Dev Portal + +Hello Admin! + + has requested Dev Portal access for . +Please visit to review this request. +``` + + +## portal_approved_email + +**Default:** `on` + +**Description:** +When enabled, developers will receive an email when access to a Dev Portal has been approved. + +``` +Subject: Dev Portal access approved + +Hello Developer! +You have been approved to access . +Please visit to login. + +``` + +## portal_reset_email + +**Default:** `on` + +**Description:** +When enabled, developers will be able to use the Reset Password flow on a Dev Portal and will receive an email with password reset instructions. + +When disabled, developers will *not* be able to reset their account passwords. + +``` +Subject: Password Reset Instructions for Dev Portal . + +Hello Developer, + +Please click the link below to reset your Dev Portal password. + + + +This link will expire in + +If you didn't make this request, keep your account secure by clicking +the link above to change your password. +``` + +## portal_reset_success_email + +**Default:** `on` + +**Description:** +When enabled, developers will receive an email after successfully reseting their Dev Portal account password. + +When disabled, developers will still be able to reset their account passwords, but will not receive a confirmation email. + +``` +Subject: Dev Portal password change success + +Hello Developer, +We are emailing you to let you know that your Dev Portal password at has been changed. + +Click the link below to sign in with your new credentials. + + +``` + + +## portal_emails_from + +**Default:** `nil` + +**Description:** +The name and email address for the 'From' header included in all Dev Portal emails. + +**Example :** + +``` +portal_emails_from = Your Name +``` + + +## portal_emails_reply_to + +**Default:** `nil` + +**Description:** +The email address for the 'Reply-To' header included in all Dev Portal emails. + + +**Example :** + +``` +portal_emails_reply_to: noreply@example.com +``` diff --git a/app/gateway/2.6.x/developer-portal/configuration/workspaces.md b/app/gateway/2.6.x/developer-portal/configuration/workspaces.md new file mode 100644 index 000000000000..2eacaeb0116e --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/configuration/workspaces.md @@ -0,0 +1,79 @@ +--- +title: Running Multiple Dev Portals with Workspaces +badge: enterprise +--- + +Kong supports running multiple instances of the Dev Portal with the use of +[**Workspaces**](/gateway/{{page.release}}/admin-api/workspaces/reference). This allows each Workspace to enable +and maintain separate Dev Portals (complete with separate files, settings, and +authorization) from within a single instance of Kong. + +## Manage Multiple Dev Portals within Kong Manager + +A snapshot of every Dev Portal within an instance of Kong can be viewed via +the Kong Manager's **Dev Portals** top navigation tab. + +This page details: + +- Whether a Dev Portal in a given Workspace is enabled or disabled +- A link to set up the Dev Portal if it is not enabled +- A link to each Dev Portal's homepage +- A link to each Dev Portal's individual overview page within Kong Manager +- Whether or not each Dev Portal is authenticated (indicated by a lock icon +in the upper right corner of each card) + +## Enable a Workspace's Dev Portal + +As with the **default** Workspace, when an additional Workspace is created, +its associated Dev Portal is `disabled` until it's manually enabled. + +This can be done from the Kong Manager by clicking the **Set up Dev Portal** +button located on the **Dev Portals** Overview page, or by navigating directly +to a Workspace's **Dev Portal Settings** page via the sidebar and toggling the +`Dev Portal Switch`, or by sending the following cURL request: + +```bash +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal=true" +``` + +On initialization, Kong will populate the new Dev Portal with the [**Default Settings**](/gateway/{{page.release}}/reference/configuration/#dev-portal) defined in Kong's configuration file. + +>*Note* A Workspace can only enable a Dev Portal if the Dev Portal feature has been enabled in Kong's configuration. + + +## Define the Dev Portal's URL structure + +The URL of each Dev Portal is automatically configured on initialization and +is determined by four properties: + +1. The `portal_gui_protocol` property +2. The `portal_gui_host` property +3. Whether the `portal_gui_use_subdomains` property is enabled or disabled +4. The `name` of the Workspace + +Example URL with subdomains disabled: `http://localhost:8003/example-workspace` + +Example URL with subdomains enabled: `http://example-workspace.localhost:8003` + +The first three properties are controlled by Kong's configuration file and +cannot be edited via the Kong Manager. + +## Override Default Settings + +On initialization, the Dev Portal will be configured using the [**Default Portal Settings**](/gateway/{{page.release}}/reference/configuration/#dev-portal) defined in Kong's configuration file. + +{:.note} +> **Note**: You can only enable a Dev Portal for a Workspace if the +Dev Portal feature has been [enabled for {{site.base_gateway}}](/gateway/{{page.release}}/developer-portal/enable-dev-portal/). + +These settings can be manually overridden in the Dev Portals **Settings** tab +in the Kong Manager or by patching the setting directly. + +## Workspace Files + +On initialization of a Workspace's Dev Portal, a copy of the **default** Dev Portal files will be made and inserted into the new Dev Portal. This allows for the easy transference of a customized Dev Portal theme and allows **default** to act as a 'master template' -- however, the Dev Portal will not continue to sync changes from the **default** Dev Portal after it is first enabled. + +## Developer Access + +Access is not synced between Dev Portals. If an Admin or Developer wants access to multiple Dev Portals, they must sign up for each Dev Portal individually. diff --git a/app/gateway/2.6.x/developer-portal/enable-dev-portal.md b/app/gateway/2.6.x/developer-portal/enable-dev-portal.md new file mode 100644 index 000000000000..77f6c69894fb --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/enable-dev-portal.md @@ -0,0 +1,66 @@ +--- +title: How To Enable the Dev Portal +badge: enterprise +--- + +Enable Dev Portal in the Kong Configuration or within a Docker container for Docker installations. + +## Enable Dev Portal in the Kong Configuration + +1. To enable the Dev Portal, the following properties must be set in the Kong +configuration file (`kong.conf`): + + ```bash + portal = on + ``` + + {{site.base_gateway}} must be **restarted** for this value to take effect. + +2. Enable the default Workspace Dev Portal via Kong Manager: + + 1. Navigate to the default Workspace in Kong Manager + 2. Click the **Settings** link under **Dev Portal** + 3. Toggle the **Dev Portal Switch** + + It may take a few seconds for the Settings page to populate. + + To enable the default Workspace's Dev portal via the command line: + + ```bash + curl -X PATCH http://localhost:8001/workspaces/default --data "config.portal=true" + ``` + + - This will expose the **default Dev Portal** at [http://localhost:8003/default](http://localhost:8003/default) + - The **Dev Portal Files endpoint** can be accessed at `:8001/files` + - The **Public Dev Portal Files API** can be accessed at `:8004/files` + +## Enable Dev Portal with Docker installation + +{:.note} +> This feature is only available with a [{{site.konnect_product_name}} Enterprise](/gateway/{{page.release}}/plan-and-deploy/licenses/) subscription. + +1. [Deploy a license](/gateway/{{page.release}}/plan-and-deploy/licenses/deploy-license/). + +2. In your Docker container, set the Portal URL and set `KONG_PORTAL` to `on`: + + ```plaintext + echo "KONG_PORTAL_GUI_HOST=localhost:8003 KONG_PORTAL=on kong reload exit" \ + | docker exec -i kong /bin/sh + ``` + + {:.note} + > The `HOSTNAME` for `KONG_PORTAL_GUI_HOST` should not be preceded by a protocol, for example, `http://`. + +3. Execute the following command: + + ```sh + curl -X PATCH --url http://localhost:8001/workspaces/default \ + --data "config.portal=true" + ``` + +4. Access the Dev Portal for the default workspace using the URL specified +in the `KONG_PORTAL_GUI_HOST` variable: + + ```sh + http://localhost:8003/default + ``` diff --git a/app/gateway/2.6.x/developer-portal/files-api.md b/app/gateway/2.6.x/developer-portal/files-api.md new file mode 100644 index 000000000000..b06409ef9818 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/files-api.md @@ -0,0 +1,159 @@ +--- +title: Using the Portal Files API +badge: enterprise +--- + +The Portal Files API can be used as an alternative to the Portal CLI to manage +dev portal content. Portal content must maintain a specific structure to render +correctly, so it is generally recommended to use the +[CLI](/gateway/{{page.release}}/developer-portal/helpers/cli/) +because it enforces that structure. The Portal Files API is useful for smaller +tasks such as managing specification, content, or theme files outside the context of +[kong-portal-templates](https://github.com/kong/kong-portal-templates). + + +Parameter | Type | Description | Required | Examples +-------------------------------:|:------:|:--------------------------:|:--------:|--------------- +`path` | `string` | The path to the file. | `yes` | `content/example.txt`, `specs/petstore.json`, `themes/base/layouts/index.html` +`contents` | `string` | The contents of the file. | `yes` | `contents=@.html`, `contents=@.json`, `contents=@.html` + +**Note:** The `@` symbol in a command automatically reads the file on disk and places +its contents into the contents argument. + +## POST a Content File + +For more details about content files, see the +[Content File documentation](/gateway/{{page.release}}/developer-portal/structure-and-file-types#content-files). + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -X POST http://localhost:8001/default/files \ + -F "path=content/homepage.html" \ + -F "contents=@.json" +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http post :8001/default/files \ + path=content/homepage.html \ + contents=@.html +``` + +{% endnavtab %} +{% endnavtabs %} + + +## POST a Spec File + +For more details about specification files, see the +[Spec File documentation](/gateway/{{page.release}}/developer-portal/structure-and-file-types#spec-files). + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -X POST http://localhost:8001/default/files \ + -F "path=specs/homepage.json" \ + -F "contents=@.json" +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http post :8001/default/files \ + path=specs/homepage.json \ + contents=@.json +``` + +{% endnavtab %} +{% endnavtabs %} + + +## POST a Theme File + +For more details about theme files, see the +[Theme File documentation](/gateway/{{page.release}}/developer-portal/structure-and-file-types#theme-files). + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -X POST http://localhost:8001/default/files \ + -F "path=themes/base/partials/header.html" \ + -F "contents=@.html" +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http post :8001/default/files \ + path=themes/base/partials/header.html \ + contents=@.html +``` + +{% endnavtab %} +{% endnavtabs %} + +## GET a File + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -X GET http://localhost:8001/default/files/content/index.txt +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http :8001/default/files/content/index.txt +``` + +{% endnavtab %} +{% endnavtabs %} + +## PATCH a File + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -X PATCH http://localhost:8001/default/files/content/index.txt \ + -F "contents=@.txt" +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http patch :8001/default/files/content/index.txt \ + contents=@.txt +``` + +{% endnavtab %} +{% endnavtabs %} + +## DELETE a File + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -X DELETE http://localhost:8001/default/files/content/index.txt +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ http delete :8001/default/files/content/index.txt +``` +{% endnavtab %} +{% endnavtabs %} diff --git a/app/gateway/2.6.x/developer-portal/helpers/cli.md b/app/gateway/2.6.x/developer-portal/helpers/cli.md new file mode 100644 index 000000000000..7fe10c224d76 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/helpers/cli.md @@ -0,0 +1,70 @@ +--- +title: Developer Portal CLI +badge: enterprise +--- + +The Kong Developer Portal CLI is used to manage your Developer Portals from the +command line. It is built using [clipanion][clipanion]. + +This is the next generation TypeScript based Developer Portal CLI. The goal of +this project is to make a higher quality CLI tool over the initial sync script. + + +## Install + +``` +> npm install -g kong-portal-cli +``` + +## Usage + +The easiest way to start is by cloning the [portal-templates repo][templates] +master branch locally. + +Next, edit `workspaces/default/cli.conf.yaml` to set workspace `name` and `rbac_token` +to match your setup. + +Make sure Kong is running and portal is on. + +Now, from the root folder of the templates repo, you can run: + +```portal [-h,--help] [--config PATH] [-v,--verbose] ``` + +Where `` is one of: + +* `config` Output or change configuration of the portal on the given +`workspace`, locally. +* `deploy` Deploy changes made locally under the given workspace upstream. +* `disable` Enable the portal on the given workspace. +* `enable` Enable the portal on the given workspace. +* `fetch` Fetches content and themes from the given workspace. +* `wipe` Deletes all content and themes from upstream workspace + +Where indicates the directory/workspace pairing you would like to operate on. + +#### For `deploy` +- Add `-W` or `--watch` to make changes reactive. +- Add `-P` or `--preserve` to avoid deleting files upstream that you do not have locally. +- Add `-D` or `--disable-ssl-verification` to disable SSL verification and use self-signed certs. +- Add `-I` or `--ignore-specs` to ignore the `/specs` directory. + +#### For `fetch` +- Add `-K` or `--keep-encode` to keep binary assets as base64-encoded strings locally. +- Add `-D` or `--disable-ssl-verification` to disable SSL verification and use self-signed certs. +- Add `-I` or `--ignore-specs` to ignore the `/specs` directory. + +#### For `wipe` +- Add `-D` or `--disable-ssl-verification` to disable SSL verification and use self-signed certs. +- Add `-I` or `--ignore-specs` to ignore the `/specs` directory. + +#### For `enable` and `disable` +- Add `-D` or `--disable-ssl-verification` to disable SSL verification and use self-signed certs. + + +[clipanion]: https://github.com/arcanis/clipanion +[sync-script]: https://github.com/Kong/kong-portal-templates/blob/81382f2c7887cf57bb040a6af5ca716b83cc74f3/bin/sync.js +[cli-support]: https://github.com/Kong/kong-portal-cli/issues/new +[cli-license]: https://github.com/Kong/kong-portal-cli/blob/master/LICENSE +[cli-contributors]: (https://github.com/Kong/kong-portal-cli/contributors) +[kong-support]: https://support.konghq.com/support/s/ +[templates]: https://github.com/Kong/kong-portal-templates diff --git a/app/gateway/2.6.x/developer-portal/index.md b/app/gateway/2.6.x/developer-portal/index.md new file mode 100644 index 000000000000..c7982b578a2d --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/index.md @@ -0,0 +1,12 @@ +--- +title: Kong Dev Portal +badge: enterprise +--- + +The Kong Dev Portal provides a single source of truth for all developers +to locate, access, and consume services. With intuitive content management for +documentation, streamlined developer onboarding, and role-based access control +(RBAC), Kong’s Dev Portal provides a comprehensive solution for creating +and customizing a unified developer experience. + +![Dev Portal](/assets/images/products/gateway/dev-portal/dev-portal-homepage.png) diff --git a/app/gateway/2.6.x/developer-portal/structure-and-file-types.md b/app/gateway/2.6.x/developer-portal/structure-and-file-types.md new file mode 100644 index 000000000000..8278a31718e4 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/structure-and-file-types.md @@ -0,0 +1,319 @@ +--- +title: Developer Portal Structure and File Types +badge: enterprise +--- + +The Kong Portal templates have been completely revamped to allow for easier customization, clearer separation of concerns between content and layouts, and more powerful hooks into Kong lifecycle/data. Under the hood, we have implemented a flat file CMS built on top of the `https://github.com/bungle/lua-resty-template` library. This system should feel familiar for anyone who has worked with projects like `jekyll`, `kirby cms`, or `vuepress` in the past. + +{:.note} +>Note: To follow along with this guide, it is best to clone the [kong-portal-templates repo](https://github.com/Kong/kong-portal-templates) and check out the `master` branch. This guide makes the assumption that you are working within a single workspace (the templates repo can host many different sets of portal files per workspace). Navigate to the `workspaces/default` directory from root to view the default workspaces portal files. + +## Directory Structure + +Navigate to `workspaces/default` from the `kong-portal-templates` root directory to access the default portals template files. The relative file structure in this directory directly maps to the file `path` schema attribute. (`content/homepage.txt` here maps to `content/homepage.txt` in Kong). + +From `workspaces/default`, you can see the different elements that make up a single instance of the kong developer portal: +- **content/** + - The content directory contains files that determine both site structure of the Kong Dev Portal as well as the dynamic content that renders within each page. +- **specs/** + - Specs are similar to content in that they contain the data needed to render dynamic content on the page. In the case of `specs`, the files contain valid OAS or Swagger to be rendered as a spec. +- **themes/** + - The theme directory contains different themes to be applied to the content of the portal. Each theme contains HTML templates, assets, and a config file that sets global styles available to the theme. +- **portal.conf.yaml** + - This config file determines which theme the portal uses to render, the name of the portal, as well configuration for special behavior such as redirect paths for user actions like login/logout. +- **router.conf.yaml (optional)** + - This optional config file overrides the portals default routing system with hardcoded values. This is useful for implementing single page applications, as well as for setting a static site structure. + +## Portal Configuration File + +### Path +- **format:** `portal.conf.yaml` +- **file extensions:** `.yaml` + +### Description +The Portal Configuration File determines which theme the portal uses to render, the name of the portal, as well as configuration for special behavior such as redirect paths for user actions like login/logout. It is required in the root of every portal. There can only be one Portal Configuration File, it must be named `portal.conf.yaml`, and it must be a direct child of the root directory. + +### Example + +```yaml +name: Kong Portal +theme: + name: light-theme +redirect: + unauthenticated: login + unauthorized: unauthorized + login: dashboard + logout: '' + pending_approval: '' + pending_email_verification: '' +collections: + posts: + output: true + route: /:stub/:collection/:name + layout: post.html +``` + +- `name`: + - **required**: true + - **type**: `string` + - **description**: The name attribute is used for meta information, such as setting a title for your portal in the browser tab. + - **example**: `Kong Portal` +- `theme` + - **required**: true + - **type**: `object` + - **description**: The theme object is used for declaring which theme you would like your portal to render, as well as theme style overrides. While the overrides are not required, declaring which theme you would like to use is. +- `redirect` + - **required**: true + - **type**: `object` + - **description**: The redirect object informs kong how to redirect the user after certain actions. If one of these values is not set, Kong serves a default template based off of the action. Each key represents the name of the action taking place, the value represents the route to which the application redirects the user. +- `collections` + - **required**: false + - **type**: `object` + - **description**: Collections are a powerful tool enabling you to render sets of content as a group. Content rendered as a collection share a configurable route pattern, as well as a layout. For more information check out the [collections](/gateway/{{page.release}}/developer-portal/working-with-templates/#collections) section of our [Working with Templates](/gateway/{{page.release}}/developer-portal/working-with-templates/) guide. + + +## Router Configuration File (Optional) + +### Path +- **format:** `router.conf.yaml` +- **file extensions:** `.yaml` + +### Description +This optional config file overrides the portals default routing system with hardcoded values. This is useful for implementing single page applications, as well as for setting a static site structure. There can only be one Router Configuration File, it must be named `router.conf.yaml`, and it must be a direct child of the root directory. + +### Example +The `router.conf.yaml` file expects sets of key-value pairs. The key should be the route you want to set; the value should be the content file path you want that route to resolve to. Routes should begin with a backslash. `/*` is a reserved route and acts as a catchall/wildcard. If the requested route is not explicitly defined in the config file, the portal will resolve to the wildcard route if present. + +```yaml +/*: content/index.txt +/about: content/about/index.txt +/dashboard: content/dashboard.txt +``` + +## Content Files + +### Path +- **format:** `content/**/*` +- **file extensions:** `.txt`, `.md`, `.html`, `.yaml`, `.json` + +### Description +Content files establish portal site structure, as well as provide its accompanying HTML layout with metadata and dynamic content at the time of render. Content files can be nested in as many subdirectories as desired as long as the parent directory is `content/`. + +In addition to providing metainfo and content for the current page at time of render, content files determine the path at which a piece of content can be accessed in the browser. + +| Content Path | Portal URL | +|-------------|---------------------------| +| `content/index.txt` | `http://portal_gui_url/` | +| `content/about.txt` | `http://portal_gui_url/about` | +| `content/documentation/index.txt` | `http://portal_gui_url/documentation` | +| `content/documentation/spec_one.txt` | `http://portal_gui_url/documentation/spec_one` | + +### Contents +``` +--- +title: homepage +layout: homepage.html +readable_by: [red, blue] +--- + +Welcome to the homepage! +``` + +File contents can be broken down into two parts: `headmatter` and `body`. + +### headmatter + +The first thing to notice in the example files contents are the two sets of `---` delimiters at the start. The text contained within these markers is called `headmatter` and always gets parsed and validated as valid `yaml`. `headmatter` contains information necessary for a file to render successfully, as well as any information you would like to access within a template. Kong parses any valid `yaml` key-value pair and becomes available within the content's corresponding HTML template. There are a few reserved attributes that have special meaning to Kong at the time of render: + +- `title`: + - **required**: false + - **type**: `string` + - **description**: The title attribute is not necessary but is recommended. When set, this will set the title of a page in the browser tab. + - **example**: `homepage` +- `layout` + - **required**: true + - **type**: `string` + - **description**: The layout attribute is required for each piece of content, and determines what HTML layout to use in order to render the page. This attribute assumes a root of the current themes layout directory (`themes//layouts`). + - **example**: `bio.html` or `team/about.html` +- `readable_by` + - **required**: false + - **type**: `array` (multiple), `string` (singular) + - **description**: The optional `readable_by` attribute determines which developers can access a piece of content. In the case of the example above, only developers with rbac roles of "red" or "blue" may access the `/homepage` route. + - **example**: `[red, blue]` (multiple), `red` (singular) + +- `route` + - **required**: false + - **type**: `string` + - **description**: This optional attribute overrides the generated route Kong assigns to content, and replaces it with the route included here. + - **example**: `route: /example/dog` renders the example page above at `/example/dog` instead of the autogenerated `/homepage` route. +- `output` + - **required**: false + - **type**: `boolean` + - **default**: `true` + - **description**: This optional attribute is `true` by default and determines whether a piece of content should be rendered. No route or page gets created when this value is set to `false`. +- `stub` + - **required**: false + - **type**: `string` + - **description**: Used by `collection` config to determine custom routing. You can read more about Collections in the collections section of the _working with templates_ guide. + +#### body +The information located under headmatter represents the content body. Body content is freeform and gets parsed as by the file extension included in the file path. In the case of the example above, the file is `.txt` and is available in the template as such. + +## Spec Files + +### Path +- **format:** `specs/**/*` +- **file extensions:** `.yaml`, `.json` + +### Description +Specs are similar to `content` files in that they provide the dynamic data needed to render a page, as well as any metadata a user wants to provide as `headmatter`. The format in which these are provided to the Portal differs from `content` files, which can be seen in the example below. + +>It is recommended to keep spec folder structure flat. Spec files must be valid OAS or Swagger `.yaml`/`.yml` or `.json` files. + +### Contents + +``` +swagger: "2.0" +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +host: petstore.swagger.io +basePath: /v1 +x-headmatter + - key1: val1 + - key2: val2 +... +``` + +Spec file contents themselves should be valid OAS or Swagger specifications. If you want +to inject headmatter into the specification, you can do so by including an `x-headmatter` +key to the root of the spec object. This may be useful if you wanted to, for example, +provide your own renderer template via `x-headmatter.layout` or override the spec's default +route via `x-headmatter.route`. + +Example: +``` +swagger: "2.0" +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +host: petstore.swagger.io +basePath: /v1 +x-headmatter: + layout: custom/my-spec-renderer.html <- Custom Layout + route: my-special-route/myfirstspec <- Custom Route +... +``` + +Specs are a collection, meaning their `layout` and `route` are determined by the +portal configuration and not the file itself. Specs are rendered by default with +the `system/spec-renderer.html` layout, under the route pattern `/documentation/:name`, +where `:name` is the name of the particular spec file. So a spec with a path of +`specs/myfirstspec.json` renders in the portal as `/documentation/myfirstspec`. +If you want to overwrite the hardcoded spec collection config, you can do so by +including your own in `portal.conf.yaml`. Check out the Collections section of +our `Working with Templates` guide to learn more. + +You can also use the [Portal Files API](/dev-portal/api/v1/) +to `POST`, `GET`, `PATCH`, and `DELETE` content, spec, and theme files. + +## Theme Files +### Themes Directory Structure +The theme directory contains different instances of portal themes, each one of which determines the look and feel of the developer portal via HTML/CSS/JS. Which theme is used at time of render is determined by setting `theme.name` within `portal.conf.yaml`. Setting `theme.name` to `best-theme` causes the portal to load theme files under `themes/best-theme/**`. + +Each theme file is composed of a few different folders: +- **assets/** + - The assets directory contains static assets that layouts/partials will reference at time of render. Includes CSS, JS, font, and image files. +- **layouts/** + - The layouts directory contains HTML page templates that `content` reference via the `layout` attribute in headmatter (see `content` section). +- **partials/** + - The partials directory contains HTML partials to be referenced by layouts. Can be compared to how layouts and partials interacted in the legacy portal. +- **theme.conf.yaml** + - This config file sets color and font defaults available to templates for reference as CSS variables. It also determines what options are available in the Kong Manager Appearance page. + +### Theme Assets + +#### Path +- **format:** `theme/*/assets/**/*` + +#### Description +The asset folder contains CSS/JS/fonts/images for your templates to reference. + +To access asset files from your templates, keep in mind that Kong assumes a path from the root of your selected theme. + +| Asset Path | Href Element | +|--------------------------|---------------------------| +| `themes/light-theme/assets/images/image1.jpeg` | `` | +| `themes/light-theme/assets/js/my-script.js` | `` | +| `themes/light-theme/assets/styles/my-styles.css` | `` | + +>Note: Image files uploaded to the `theme/*/assets/` directory should either be a svg text string or `base64` encoded, `base64` images will be decoded when served. + +### Theme Layouts + +#### Path +- **format:** `theme/*/layouts/**/*` +- **file extensions:** `.html` + +#### Description +Layouts act as the HTML skeleton of the page you want to render. Each file within the layouts directory must have an `html` filetype. They can exist as vanilla `html`, or can reference partials and parent layouts via the portals templating syntax. Layouts also have access to the `headmatter` and `body` attributes set in `content`. + +The example below shows what a typical layout could look like. + +{% raw %} +```html +
+ {(partials/header.html)} <- syntax for calling a partial within a template +
+
+

{{page.title}}

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

{{page.body}}

<- 'body' retrieved from page body +
+
+ {(partials/footer.html)} +
+``` +{% endraw %} + +To learn more about the templating syntax used in this example, check out our [templating guide](/gateway/{{page.release}}/developer-portal/working-with-templates/). + +### Theme Partials + +#### Path +- **format:** `theme/*/partials/**/*` +- **file extensions:** `.html` + +#### Description +Partials are very similar to layouts: they share the same syntax, can call other partials within themselves, and have access to the same data/helpers at time of render. The thing that differentiates partials from layouts it that layouts call on partials to build the page, but partials cannot call on layouts. + +The example below shows the `header.html` partial referenced from the example above: + +{% raw %} +```html +
+
+
+ <- can access the same page data the parent layout +
+
+ {(partials/header_nav.html)} <- partials can call other partials +
+
+
+``` +{% endraw %} + +### Theme Configuration File + +#### Path +- **format:** `theme/*/theme.conf.yaml` +- **file extensions:** `.yaml` + +#### Description +The Theme Configuration File determines color/font/image values a theme makes available for templates/CSS at the time of render. It is required in the root of every theme. There can only be one Theme Configuration File, it must be named `theme.conf.yaml`, and it must be a direct child of the themes root directory. diff --git a/app/gateway/2.6.x/developer-portal/theme-customization/adding-javascript-assets.md b/app/gateway/2.6.x/developer-portal/theme-customization/adding-javascript-assets.md new file mode 100644 index 000000000000..06a364245ff4 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/theme-customization/adding-javascript-assets.md @@ -0,0 +1,56 @@ +--- +title: Adding and Using JavaScript Assets in Kong Dev Portal +badge: enterprise +--- + +The Kong Developer Portal ships with Vue, React, and jQuery already loaded. +You may want to make use of these libraries to write custom interactive +webpages or load additional JavaScript. + +> Note: This guide is for adding/using JavaScript assets without changing server-side routing. [Learn more about a SPA to the Dev Portal](/gateway/{{page.release}}/developer-portal/theme-customization/single-page-app/). + +## Prerequisites + +* {{site.base_gateway}} 1.3 or later +* Portal Legacy is turned off +* The Kong Developer Portal is enabled and running +* The [kong-portal-cli tool](/gateway/{{page.release}}/developer-portal/helpers/cli/) is installed locally + + +## Adding JS Assets +> Warning: Due to compatibility issues, avoid using any React version other than React 15 on the `layouts/system/spec-render.html` layout. We recommend using the version of React included by the default base theme. + +To add JavaScript assets: +1. Clone the [kong-portal-templates](https://github.com/Kong/kong-portal-templates) repo. +2. Add any JavaScript files to the `themes/base/js` folder. +3. Deploy using the [kong-portal-cli-tool](/gateway/{{page.release}}/developer-portal/helpers/cli/). + + +## Loading JS Assets + +You can make use of the existing Vue and jQuery in any layout/partial that includes `partials/theme/required-scripts.html` where these scripts are loaded. + +By default, React is only loaded on `layouts/system/spec-render.html`. + +If you want to load React or any custom JavaScript asset on all pages, you can edit `themes/partial/foot.html`. + + +{% raw %} +``` +{% layout = "layouts/_base.html" %} + +{-main-} + {(partials/header.html)} + +
+ {* blocks.content *} +
+ + {(partials/footer.html)} + + +{-main-} +``` +{% endraw %} + +Alternatively, you can load the script you need on the specific layout for each content page as needed. diff --git a/app/gateway/2.6.x/developer-portal/theme-customization/easy-theme-editing.md b/app/gateway/2.6.x/developer-portal/theme-customization/easy-theme-editing.md new file mode 100644 index 000000000000..81e56a3988d6 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/theme-customization/easy-theme-editing.md @@ -0,0 +1,23 @@ +--- +title: Easy Theme Editing in Kong Manager +badge: enterprise +--- + +The Kong Developer Portal ships with a default theme, including preset images, background colors, fonts, and button styles. These settings can be edited quickly and easily from within Kong Manager, without the need to edit code. + +## Prerequisites + +* {{site.base_gateway}} 1.3 or later +* Access to Kong Manager +* The Developer Portal is enabled and running + +## The Appearance Tab + +From the **Workspace** dashboard in **Kong Manager**, click on the **Appearance** tab under **Dev Portal** on the left side bar. +This will open the Developer Portals theme editor. From this page, the header logo, background colors, font colors, and button styles can be edited using the color picker interface. + +Hovering over an element will show a color picker, as well as a list of predefined colors. These colors are defined by the current template and can be edited in the [theme.conf.yaml](#editing-theme-files-with-the-editor) file + +## Editing Theme Files with the Editor + +The Dev Portal Editor within Kong Manager exposes the default Dev Portal theme files. The theme files can be found at the bottom of the file list under *Themes*. The variables exposed in the *Appearance* tab can be edited in the `theme.conf.yaml` file. See [Using the Editor](/gateway/{{page.release}}/developer-portal/using-the-editor/) for more information on how to edit, preview, and save files in the Editor. diff --git a/app/gateway/2.6.x/developer-portal/theme-customization/emails.md b/app/gateway/2.6.x/developer-portal/theme-customization/emails.md new file mode 100644 index 000000000000..44f9dd65e2fa --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/theme-customization/emails.md @@ -0,0 +1,204 @@ +--- +title: Customizing Portal Emails +badge: enterprise +--- + +You can manage the message and appearance of emails being sent by the Kong Developer Portal. +Editable email templates are loaded as files similar to content files for portal rendering. +Email files can be managed in the same way as other files for rendering, via editor or via the Portal CLI Tool. +This feature is **not** supported on legacy portal mode. + +If no email templates are loaded, Kong will fall back to the same emails as {{site.base_gateway}} 1.3.0.0. +Enabling a non-legacy portal on new workspaces loads default editable email templates. +For existing non-legacy Portals, editable email templates must be loaded manually. + +Email-specific values are templated in tokens that work similarly to templating in portal layouts and partials. +Not all tokens are supported on all emails. + +## Prerequisites + +* The Kong Developer Portal is not running in **Legacy Mode** +* The Kong Developer Portal is enabled and running +* [The emails you want are enabled in kong](/gateway/{{page.release}}/developer-portal/configuration/smtp/#portal_invite_email) +* If using CLI tool, kong-portal-cli tool 1.1 or later is installed locally and git installed + +## Understanding Email Files + +Portal templates use a combination of HTML, markdown, and [`tokens`](#token-descriptions). + +The follow example is the `emails/approved-access.txt` template: + + +{% raw %} +```yaml +--- +layout: emails/email_base.html + +subject: Developer Portal access approved {{portal.url}} +heading: Hello {{email.developer_name}}! +--- +You have been approved to access {{portal.url}}. +
+Please visit {{portal.url}}/login to login. +``` +{% endraw %} + +Like other content files, these files have a headmatter between the two `---` . The layout is set by `layout` attribute, this is the layout file this email will render with. + +- `subject` sets the subject line for email. +- `heading` is an optional value that by default is rendered as a h3 + +The body of the email is HTML content. You can reference the tokens allowed for the email in the table below. In this case, {% raw %}`{{portal.url}}`{% endraw %} is used to access the portal url + +## Supported Emails and Tokens + +{% raw %} +|Path |Supported Tokens |Required Tokens |Description| +|--- |--- |--- |--- | +|`emails/invite.txt` | `{{portal.gui_url}}` `{{email.developer_email}}` | `{{portal.gui_url}}` |email sent to developer who is invited to a portal from the manager | +|--- |--- |--- |--- | +|`emails/request-access.txt` |`{{portal.gui_url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` `{{email.admin_url}}` |`{{portal.gui_url}}` `{{email.developer_email}}` |email sent to admin when a developer signs up for portal, in order to approve the developer | +|`emails/approved-access.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` |`{{portal.gui_url}}` |email sent to developer when their account is approved | +|`emails/password-reset.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` `{{email.token}}` `{{email.token_exp}}` `{{email.reset_url}}` |`{{portal.url}}` `{{email.token}}` or `{{email.reset_url}}` |email sent to developer when a password reset is requested (basic-auth only) | +|`emails/password-reset-success.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` |`{{portal.url}}` |email sent to developer when a password reset is successful (basic-auth only) | +|emails/account-verification.txt |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` `{{email.token}}` `{{email.verify_url}}` `{{email.invalidate_url}}` |`{{portal.url}}` `{{email.token}}` or both `{{email.verify_url}}` and `{{email.invalidate_url}} ` |email sent to developer when `portal_email_verification` is on to verify developer email (basic-auth only) | +|`emails/account-verification-approved.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` |`{{portal.url}}` |email sent to developer when `portal_email_verification` is on and developer has verified email and developer has been approved by admin/auto-approve is on (basic-auth only) | +|`emails/account-verification-pending.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` |`{{portal.url}}` |email sent to developer when `portal_email_verification` is on and developer has verified email and developer has yet to be approved by admin (basic-auth only) | +{% endraw %} + +## Token Descriptions + +{% raw %} +|Token |Description | +|--- |--- | +|`{{portal.url}}` |Dev Portal URL for the workspace | +|--- |--- | +|`{{email.developer_email}}` |Developer's email | +|`{{email.developer_name}}` |Developer's full name, this value is collected as part of registration by default. If meta-fields are edited to not include full_name then this will fallback to email | +|`{{email.developer_meta.*}}` |Developer's meta-fields, these value are collected as part of registration. They must be configured prior to registration. If the value doesn't exist or is optional and blank, it will display as an empty string. If the `developer_meta` configuration doesn't specify the field, it will appear as-is without replacement, e.g. `{{email.developer_meta.preferred_name}}`| +|`{{email.admin_url}}` |Kong Manager URL | +|`{{email.reset_url}}` |Dev Portal full URL for resetting password (assumes default path for password reset) | +|`{{email.token_exp}}` |Human readable string for amount of time from sending of email, password reset token/url is valid. | +|`{{email.verify_url}}` |Link to verify account (assumes default path for account verification)) | +|`{{email.invalidate_url}}` |Link to invalidate account verification request (assumes default path for account verification)) | +|`{{email.token}}` |Can be used in combination with `{{portal.url}}` to manually build url string for password reset and account verification/invalidation. **Not recommended for use**, unless custom path for password reset or account verification has been set. | +{% endraw %} + +## Editing Email Templates + +The default email templates will be automatically loaded into the Kong Developer Portal's file system when the Dev Portal is activated. These templates can now be edited in Kong Manager via the **Portal Editor** or via the **Portal CLI** tool. + +### Editing via the Portal Editor + +Email templates can now be edited in the Portal Editor along with the rest of the files in the Kong Developer Portal file system. To view and edit these files: + +1. Log into Kong Manager and navigate to the Workspace whose Dev Portal you wish to edit. +2. Select the **Editor** from the sidebar under **Dev Portal**. + +The email templates can be found under the **Emails** section in the Portal Editor sidebar. + +### Editing via the Portal CLI Tool + +1. Clone [https://github.com/Kong/kong-portal-templates] master branch, and navigate into its directory. +2. If you have any customizations or permissions changes that you want to keep: + Run `portal fetch ` This will pull in your modifications locally. +3. After making any changes, `portal deploy ` to deploy all files. + +## Editing Email Appearance + +To edit the appearance of emails, you can change the layout file emails use. +By default, emails are set to use the layout `emails/email_base.html`. If this file does not exist inside your theme (default theme is `base`), then a hardcoded fallback will be used. + +You can edit the layout this layout file via the Portal Editor or locally with the Portal CLI tool. Follow the instructions for the editing email text, but modifying the layout file instead. + +If you want different emails to have a different appearance, you can set different layout files for each email file. + +The default email layout looks like: + +{% raw %} +```html + + + + + + {{portal.name}} +

{{page.heading}}

+

+ {*page.body*} +

+ + +``` +{% endraw %} + +The `img` tag loads the logo that can be set in the appearance tab in the manager. If you do not want to display a logo, remove the `` tag. If you want to set different sizing for your logo, you can change the inline style attribute. + +{:.note} +> The logo will not render for many email clients that pre-fetch images if portal is not set to be accessible from a public url (for example if you are testing the Portal with a localhost). + +By modifying the HTML of this file, you can change the appearance of your emails. For example if you wanted to add a footer that would show on all emails, add it under the `

` tag + +Be sure to keep in mind the HTML support limitations of the email clients you plan to support. + +## Loading Email Templates on Existing Dev Portals + +Editable email templates can be loaded either via the editor or via the `kong-portal-cli` tool. + +### Load Email Templates via the Portal Editor + +1. Log into Kong Manager and navigate to the workspace you want to edit. Click on **Editor** in the sidebar. +2. Click **New File+**. +3. Select Content type `email`. +4. Type in one of the supported paths from above. +5. Click **Create File** to generate a default email template that is valid for that email. +6. Do this for emails you want to edit. + + Note: By default, these emails you create will have layout key set: `layout: emails/email_base.html`. + If you don’t create this layout file, all emails fallback to a default layout. + You will want to create this layout if you want to customize the Appearance of emails in addition to message. + +To create an email layout: + +1. Click **New File+**. +2. Select Content type `theme`. +3. Type in the path for the layout, `themes//layouts/email_base.html`. The default theme name is base. + The layout that loads in the new portals in 1.3.0.1 is the following (this adds the logo image that can be set in the appearance tab in the manager): + +{% raw %} +```html + + + + + + {{portal.name}} +

{{page.heading}}

+

+ {*page.body*} +

+ + +``` +{% endraw %} + +Find out more about customizing the email layout in the section below. + +### Load Email Templates via the Portal CLI Tool + +1. Clone the [portal templates master branch](https://github.com/Kong/kong-portal-templates) and + navigate into the folder you cloned. +2. If you have any customizations or permissions changes that you want to keep: + + 1. Run `portal fetch `. This pulls in your modifications locally. + + 2. Merge in the portal templates master branch + to apply changes for 1.3.0.1, including emails. + +3. Run `portal deploy `. This deploys all files. diff --git a/app/gateway/2.6.x/developer-portal/theme-customization/markdown-extended.md b/app/gateway/2.6.x/developer-portal/theme-customization/markdown-extended.md new file mode 100644 index 000000000000..b9345e5e6e78 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/theme-customization/markdown-extended.md @@ -0,0 +1,44 @@ +--- +title: Markdown Rendering Module +badge: enterprise +--- + +The Kong Developer Portal supports +[Github-flavored markdown](https://github.github.com/gfm/) (GFM) that can be +used in lieu of the [templates](/gateway/{{page.release}}/developer-portal/working-with-templates/). Instead of having to +create an HTML layout and partials for your templates, you can use custom CSS +with the improved markdown rendering module. The extended markdown support +improves rendering significantly, especially for tables. + +## Prerequisites + +* {{site.base_gateway}} 2.1 or later +* Access to Kong Manager +* The Developer Portal is enabled and running + +## Specify the markdown rendering module in a document + +1. Create a markdown file for your Dev Portal documentation. +2. Call the markdown module using the `layout` parameter. +3. Specify the `.css` file you want to use. You can use the default Github `.css` as shown, or specify your own custom `.css`. + + - All markdown CSS classes should be prepended by `.markdown-body`. This is + to ensure that markdown styles do not bleed into other areas of the portal. + - The `.css` file should be placed in the current theme's `/assets` directory. + - The renderer assumes the `.css` path will begin from the `/assets` + directory. See the example below. + - Other classes defined in any other Dev Portal CSS external to the + `markdown.css` may pollute your rendered markdown. If you want to unset + particular styles, you can do so using the + `/assets/style/markdown-fixes.css` file. + +### Example + +`/content/markdown-example.md` + +``` +--- +layout: system/markdown.html +css: assets/style/markdown.css +--- +``` diff --git a/app/gateway/2.6.x/developer-portal/theme-customization/single-page-app.md b/app/gateway/2.6.x/developer-portal/theme-customization/single-page-app.md new file mode 100644 index 000000000000..f17fbf4cd684 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/theme-customization/single-page-app.md @@ -0,0 +1,144 @@ +--- +title: Hosting Single Page App out of Kong Dev Portal +badge: enterprise +--- + +The Kong Developer Portal ships with a default server-side rendered theme; however, it is possible to replace this with a Single Page App (SPA). This example is in Angular using the Angular CLI Tool, but you can follow along with any other JavaScript framework with just a few tweaks. + +To view the basic example Angular template from this guide, visit the [`example/spa-angular`](https://github.com/Kong/kong-portal-templates/tree/example/spa-angular) branch from the `kong-portal-templates branch`. + +## Prerequisites + +* Portal Legacy is turned off +* The Developer Portal is enabled and running +* kong-portal-cli tool is installed locally + +## What is a SPA + +A Single Page App (SPA) is a website that loads all HTML, JavaScript, and CSS on the first load. Instead of loading subsequent pages from the server, JavaScript is used to dynamically change the page content. You may want to use an SPA in Dev Portal if you have a preexisting SPA you want to integrate with the portal, or you are trying to achieve a more application-like experience across many pages. An SPA takes control of routing from the server, and handles it client-side instead. + +Custom JavaScript can also be added to run only on specific layouts, allowing you to maintain server-side rendering. [Learn more](/gateway/{{page.release}}/developer-portal/theme-customization/adding-javascript-assets/) about adding JavaScript to a layout without implementing an SPA. + +## Making Choices + + +We recommend Catalog and Spec routes not be handled by SPA. +If you are using Authentication, then you probably also want to leave server-side rendering for any account pages. + +## Getting Started + +Clone the [portal-templates](https://github.com/Kong/kong-portal-templates) repo + +Create a file called `router.conf.yaml` in `workspaces/default` This file will override the default routing, allowing you to control routing via JavaScript. + +`router.conf.yaml` must be a yaml file, where the key is each route, and the value a content or spec path. `/*` Is a catch-all wildcard for all routes not specified in `router.conf.yaml`, it will overwrite all default routing set by collections or set in headmatter. + +In the `router.conf.yaml` example below, we are hardcoding routing for all kong related functionality and deferring to SPA routing for all other routes. The `/*` route at the bottom of the file is a wildcard route. The wildcard route, in this case, tells Kong to serve `content/index.txt` for any request that is not handled by the route declarations above. + +``` +/login: content/login.txt +/logout: content/logout.txt +/register: content/register.txt +/settings: content/settings.txt +/reset-password: content/reset-password.txt +/account/invalidate-verification: content/account/invalidate-verification.txt +/account/resend-verification: content/account/resend-verification.txt +/account/verify: content/account/resend-verification.txt +/documentation: content/documentation/index.txt +/documentation/httpbin: specs/httpbin.json +/documentation/petstore: specs/petstore.yaml +/*: content/index.txt + +``` + +### Create your SPA + +Create an SPA app in the JavaScript framework of your choice. This +example uses angular. + +``` +ng new +``` + +Make sure to include a 404 route, as well as all routes you want to have on the Portal (excluding the routes handled by server-side rendering excluded above). + +Run the build process + +For angular: + +``` +ng build +``` + +Copy the build output JS and CSS files to a folder inside `workspaces/default/themes/assets/js`. + +For this example, place the angular build inside a `workspaces/default/themes/assets/js/ng`. + +### Mounting an SPA + +To load our JS, we need to mount it. Let's create a new layout page. + +Create a file called `spa.html` in `workspaces/default/themes/layouts`. + +This file will need to contain the HTML element that the SPA will mount to as well as the scripts necessary to do this. +For reference, view the `index.html` inside the build folder created by the build step of the SPA. + +The example uses `layouts/_base.html` as the base for the layout template. +By doing so, the element is handled the same way as other pages in the portal, as well as the same CSS and scripts. + +If you want to have the top nav bar and bottom nav bar, be sure to include them in your layout. + +This is the resulting layout: + +{% raw %} +``` +{% layout = "layouts/_base.html" %} +{-main-} + + {(partials/header.html)} +
+ +
+ {(partials/footer.html)} + + + + + + + + + + + + + +{-main-} +``` +{% endraw %} + +If the SPA build process creates a CSS file, edit the `head.html` partial to include your CSS file. + +### Loading your layout + +Modify `workspaces/default/content/index.txt` to use your layout. +The title you set here will be the one that displays until the JS set title loads. + +{% raw %} +``` +--- +layout: spa.html +title: Home +--- +``` +{% endraw %} + +### Deploy the Portal + +Now using the kong-portal-cli tool, deploy the portal. + +From the root folder of the templates repo: + +``` +portal deploy default +``` diff --git a/app/gateway/2.6.x/developer-portal/using-the-editor.md b/app/gateway/2.6.x/developer-portal/using-the-editor.md new file mode 100644 index 000000000000..dd8d78265a62 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/using-the-editor.md @@ -0,0 +1,55 @@ +--- +title: Using the Editor through Kong Manager +badge: enterprise +--- + +Kong Manager offers a robust file editor for editing the template files of the Dev Portal from within the browser. + +## Prerequisites + +* {{site.base_gateway}} 1.3 or later +* Access to Kong Manager +* The Kong Developer Portal is **enabled** and **running** + +>NOTE: Editor Mode is *not* available when running the Dev Portal in **legacy** mode. + +## Enter Editor Mode + +From the **Kong Manager** dashboard of your **Workspace**, click **Editor** under **Dev Portal** in the sidebar. + +This will launch the **Editor Mode**. + +## Navigating the Editor + +When enabled, the Dev Portal is pre-populated with Kong's default theme. The file editor exposes these files to the UI, allowing them to be edited quickly and easily from inside the browser. When you first open the editor, you will be presented with a list of files on the left, and a blank editing form. + +1. Create new files for the Dev Portal right from the Editor by clicking `New File+`. +2. List of all exposed template files in the Dev Portal, separated by Content / Spec / Themes. +3. Code View - Select a file from the sidebar to show the code here. +4. Portal Preview - View a live preview of the selected Dev Portal file. +5. Toggle View - Choose between three different views: full screen code, split view, and full screen preview mode. + +## Editing Files + +Select a file from the sidebar to open it for editing. This will expose the file to the Code View and show a live update in the Portal Preview. Clicking Save in the top right corner will save the updates to the database and update the file on the Dev Portal. + +## Adding new files + +Clicking the `New File +` button opens the New File Dialog. + +Once created, files will immediately be available from within the Editor. + + +## Authenticating files + +Authentication is handled by `readable_by` value on content pages (for gui view, go to permissions page) + - set `readable_by`: '*' to equal old authenticated + - to restrict access to certain roles, set `readable_by` to an array of accepted roles (you must first create roles on the permissions page) + - for specs, `readable_by` is set inside the `x-headmatter` object + + +## Deleting files + +To delete a file from within the Editor, right click on the filename and select **Delete** from the popup menu. + +**NOTE:** This action cannot be undone. diff --git a/app/gateway/2.6.x/developer-portal/working-with-templates.md b/app/gateway/2.6.x/developer-portal/working-with-templates.md new file mode 100644 index 000000000000..eea12b573988 --- /dev/null +++ b/app/gateway/2.6.x/developer-portal/working-with-templates.md @@ -0,0 +1,1416 @@ +--- +title: Working with Templates +badge: enterprise +--- + +Kong Portal is built on top of the `lua-resty-template` templating library, which can be viewed here: [https://github.com/bungle/lua-resty-template](https://github.com/bungle/lua-resty-template). Basic usage of the library will be described below. Refer to the source documentation for a more in-depth look at what it can accomplish. + +## Syntax +***(excerpt from lua-resty-templates documentation)*** + +You may use the following tags in templates: +{% raw %} +* `{{expression}}`, writes result of expression - HTML escaped +* `{*expression*}`, writes result of expression +* `{% lua code %}`, executes Lua code +* `{(path-to-partial)}`, include `partial` file by path, you may also supply context for the file `{(partials/header.html, { message = "Hello, World" } )}` + +* `{-block-}...{-block-}`, wraps inside of a `{-block-}` to a value stored in a `blocks` table with a key `block` (in this case), see [using blocks](https://github.com/bungle/lua-resty-template#using-blocks). Don't use predefined block names `verbatim` and `raw`. +* `{-verbatim-}...{-verbatim-}` and `{-raw-}...{-raw-}` are predefined blocks whose inside is not processed by the `lua-resty-template` but the content is outputted as is. +* `{# comments #}` everything between `{#` and `#}` is considered to be commented out (i.e., not outputted or executed). +{% endraw %} + +## Show custom properties + +You may work with custom properties in your OpenAPI spec. To expose custom properties in Dev Portal, change the property `showExtensions` to `true` in the `spec-renderer.html` file. By default, `showExtensions` is `false`. + +## Partials + +Partials are snippets of HTML that layouts can reference. Partials have access to all the same data that its layout does, and can even call other partials. Breaking your code into partials can help organize large pages, as well as allow different layouts share common page elements. + +### content/index.txt + +{% raw %} +``` +--- +layout: index.html +title: Partials +header_logo: assets/images/example.jpeg +header_nav_items: + about: + href: /about + guides: + href: /guides +hero_title: Partials Info +hero_description: Partials are wicked sick! +--- +``` +{% endraw %} + +### layouts/index.html + +{% raw %} +```html +{(partials/header.html)} +
+ {(partials/hero.html)} +
+{(partials/footer.html)} +``` +{% endraw %} + +### partials/header.html + +{% raw %} +```html +
+
+ +
+
+ {(partials/header_nav.html)} +
+
+``` +{% endraw %} + +### partials/header_nav.html + +{% raw %} +``` html +
    + {% for title, href in each(page.header_nav_items) do %} +
  • {{title}}
  • + {% end %} +
+``` +{% endraw %} + +### partials/hero.html + +{% raw %} +``` html +

{{page.hero_title}}

+

{{page.hero_description}}

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

footer

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

Partials Info

+

Partials are wicked sick!

+
+

footer

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

{{page.title}}

+

{{page.description}}

+

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

header

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

footer

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

header

+
+
+

Blocks

+

Blocks are the future!

+

+
+

footer

+
+ + +``` +{% endraw %} + +## Collections +Collections are a powerful tool enabling you to render sets of content as a group. Content rendered as a collection share a configurable route pattern, as well as a layout. Collections are configured in your portals `portal.conf.yaml` file. + +The example below shows all the necessary configuration/files needed to render a basic `blog` collection made up of individual `posts`. + +#### portal.conf.yaml + +{% raw %} +``` +name: Kong Portal +theme: + name: base +collections: + posts: + output: true + route: /:stub/:collection/:name + layout: post.html +``` +{% endraw %} + +Above you can see a `collections` object was declared, which is made up of individual collection configurations. In this example, you are configuring a collection called `posts`. The renderer looks for a root directory called `_posts` within the `content` folder for individual pages to render. If you created another collection conf called `animals`, the renderer would look for a directory called `_animals` for content files to render. + +Each configuration item is made up of a few parts: +- `output` + - **required**: false + - **type**: `boolean` + - **description**: This optional attribute determines whether the collections should render or not. When set to `false`, virtual routes for the collection are not created. +- `route` + - **required**: true + - **type**: `string` + - **default**: `none` + - **description**: The `route` attribute is required and tells the renderer what pattern to generate collection routes from. A collection route should always include at least one valid dynamic namespace that uniquely identifies each collection member. + - Any namespace in the route declaration which begins with `:` is considered dynamic. + - Only certain dynamic namespaces are recognized by Kong as valid: + - `:title`: Replaces namespace with a contents `title`, declared in headmatter. + - `:name`: Replaces namespace with the filename of a piece of content. + - `:collection`: Replaces namespace with name of current collection. + - `:stub`: Replaces namespace with value of `headmatter.stub` in each contents headmatter. +- `layout` + - **required**: true + - **type**: `string` + - **description**: The `layout` attribute determines what HTML layout the collections use to render. The path root is accessed from within the current themes `layouts` directory. + +### content/_posts/post1.md + +{% raw %} +``` +--- +title: Post One +stub: blog +--- + +This is my first post! +``` +{% endraw %} + + +### content/_posts/post2.md + +{% raw %} +``` +--- +title: Post Two +stub: blog +--- + +This is my second post! +``` +{% endraw %} + +### themes/base/layouts/post.html + +{% raw %} +```html +

{{ page.title }}

+

{* page.body *}

+``` +{% endraw %} + +Output: + +From `/blog/posts/post1`: + +```html +

Post One

+

This is my first post!

+``` + +From `/blog/posts/post2`: + +```html +

Post Two

+

This is my second post!

+``` + + +## Kong Template Helpers - Lua API +Kong Template Helpers are a collection of objects that give access to your portal data at the time of render and provide powerful integrations into Kong. + +Global: + +- [`l`](#lkey-fallback) - Locale helper, first version, gets values from the currently active page. +- [`each`](#eachlist_or_table) - Commonly used helper to iterate over lists or tables. +- [`print`](#printany) - Commonly used helper to print lists / tables. +- [`markdown`](#printany) - Commonly used helper to print lists / tables. +- [`json_decode`](#json_decode) - Decode JSON to Lua table. +- [`json_encode`](#json_encode) - Encode Lua table to JSON. + +Objects: + +- [`portal`](#portal) - The portal object refers to the current workspace portal being accessed. +- [`page`](#page) - The page object refers to the currently active page and its contents. +- [`user`](#user) - The user object represents the currently logged in developer accessing the Kong Portal. +- [`theme`](#theme) - The theme object represents the currently active theme and its variables. +- [`tbl`](#tbl) = Table helper methods. Examples: `map`, `filter`, `find`, `sort`. +- [`str`](#str) = String helper methods. Examples: `lower`, `upper`, `reverse`, `endswith`. +- [`helpers`](#helpers) - Helper functions simplify common tasks or provide easy shortcuts to Kong Portal methods. + + +Terminology / Definitions: + +- `list` - Also referred to commonly as an array (`[1, 2, 3]`) in Lua is a table-like object (`{1, 2, 3}`). Lua list index starts at `1` not `0`. Values can be accessed by array notation (`list[1]`). +- `table` - Also commonly known as an object or HashMap (`{1: 2}`) in Lua looks like (`{1 = 2}`). Values can be accessed by array or dot notation (`table.one or table["one"]`). + +### l(key, fallback) + +Returns the current translation by key from the currently active page. + +#### Return Type +{% raw %} + +```lua +string +``` +{% endraw %} + +#### Usage + +Using `content/en/example.txt`: + +{% raw %} +```yaml +--- +layout: example.html + +locale: + title: Welcome to {{portal.name}} + slogan: The best developer portal ever created. +--- +``` +{% endraw %} + + +Using `content/es/example.txt`: + +{% raw %} +```yaml +--- +layout: example.html + +locale: + title: Bienvenido a {{portal.name}} + slogan: El mejor portal para desarrolladores jamás creado. +--- +``` +{% endraw %} + + +Using `layouts/example.html`: + +{% raw %} +```lua +

{* l("title", "Welcome to" .. portal.name) *}

+

{* l("slogan", "My amazing developer portal!") *}

+

{* l("powered_by", "Powered by Kong.") *}

+``` +{% endraw %} + + +Output: + +For `en/example`: + +{% raw %} +```html +

Welcome to Kong Portal

+

The best developer portal ever created.

+

Powered by Kong.

+``` +{% endraw %} + + +For `es/example`: + +{% raw %} +```html +

Bienvenido a Kong Portal

+

El mejor portal para desarrolladores jamás creado.

+

Powered by Kong.

+``` +{% endraw %} + + +#### Notes + +- `l(...)` is a helper from the `page` object. It can be also accessed via `page.l`. However, `page.l` does not support template interpolation (for example, `{{portal.name}}` will not work.) + +### each(list_or_table) + +Returns the appropriate iterator depending on what type of argument is passed. + +#### Return Type + +```lua +Iterator +``` + +#### Usage + +Template (List): + +{% raw %} +```lua +{% for index, value in each(table) do %} +
    +
  • Index: {{index}}
  • +
  • Value: {{ print(value) }}
  • +
+{% end %} +``` +{% endraw %} + + +Template (Table): + +{% raw %} +```lua +{% for key, value in each(table) do %} +
    +
  • Key: {{key}}
  • +
  • Value: {{ print(value) }}
  • +
+{% end %} +``` +{% endraw %} + +### print(any) + +Returns the output of an input value as a string. + +#### Return Type + +```lua +string +``` + +#### Usage + +Template (Table): + +{% raw %} +```lua +
{{print(page)}}
+``` +{% endraw %} + +### markdown(string) + +Returns HTML from the markdown string passed as an argument. If a string argument is not valid markdown, the function will return the string as is. To render properly, the helper should be used with raw `{* *}` delimiters. + +#### Return Type + +```lua +string +``` + +#### Usage + +Template (string as an argument): + +{% raw %} +```lua +
{* markdown("##This is Markdown") *}
+``` +{% endraw %} + +Template (content val as an argument): + +{% raw %} +```lua +
{* markdown(page.description) *}
+``` +{% endraw %} + +### json_encode(object) + +JSON encodes Lua table passed as argument + +#### Return Type + +```lua +string +``` + +#### Usage + +Template: + +{% raw %} +```lua +
{{ json_encode({ dog = cat }) }}
+``` +{% endraw %} + +### json_decode(string) + +Decodes JSON string argument to Lua table + +#### Return Type + +```lua +table +``` + +#### Usage + +Template: + +{% raw %} +```lua +
{{ print(json_encode('{"dog": "cat"}')) }}
+``` +{% endraw %} + +### `portal` + +`portal` gives access to data relating to the current portal, this includes things like portal configuration, content, specs, and layouts. + + - [`portal.workspace`](#portalworkspace) + - [`portal.url`](#portalurl) + - [`portal.api_url`](#portalapi_url) + - [`portal.auth`](#portalauth) + - [`portal.specs`](#portalspecs) + - [`portal.specs_by_tag`](#portalspecs_by_tag) + - [`portal.developer_meta_fields`](#portaldeveloper_meta_fields) + +You can access the current workspace portal config directly on the `portal` object like so: + +```lua +portal[config_key] or portal.config_key +``` + +For example `portal.auth` is a portal config value. You can find a list of config values by reading the portal section of `kong.conf`. + +#### From kong.conf + +The portal only exposes config values that start with `portal_`, and they can be access by removing the `portal_` prefix. + +Some configuration values are modified or customized, these customizations are documented under the [Portal Members](#portal-members) section. + +##### portal.workspace + +Returns the current portal's workspace. + +##### Return Type + +```lua +string +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{portal.workspace}} +``` +{% endraw %} + +Output: + +```html +default +``` + +#### portal.url + +Returns the current portal's url with workspace. + +##### Return Type + +```lua +string +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{portal.url}} +``` +{% endraw %} + +Output: + +```html +http://127.0.0.1:8003/default +``` + +#### portal.api_url + +Returns the configuration value for `portal_api_url` with +the current workspace appended. + +##### Return Type + +```lua +string or nil +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{portal.api_url}} +``` +{% endraw %} + +Output when `portal_api_url = http://127.0.0.1:8004`: + +```html +http://127.0.0.1:8004/default +``` + +#### portal.auth + +Returns the current portal's authentication type. + +##### Return Type + +```lua +string +``` + +##### Usage + +**Printing a value** + +Input: + +{% raw %} +```hbs +{{portal.auth}} +``` +{% endraw %} + +Output when `portal_auth = basic-auth`: + +```html +basic-auth +``` + +**Checking if authentication is enabled** + +Input: + +{% raw %} +```hbs +{% if portal.auth then %} + Authentication is enabled! +{% end %} +``` +{% endraw %} + +Output when `portal_auth = basic-auth`: + +```html +Authentication is enabled! +``` + +#### portal.specs + +Returns an array of specification files contained within the current portal. + +##### Return type + +```lua +array +``` + +##### Usage + +**Viewing a content value** + +Template: + +{% raw %} +```hbs +
{{ print(portal.specs) }}
+``` +{% endraw %} + +Output: + +```lua +{ + { + "path" = "content/example1_spec.json", + "content" = "..." + }, + { + "path" = "content/documentation/example1_spec.json", + "content" = "..." + }, + ... +} +``` + +**Looping through values** + +Template: + +{% raw %} +```hbs +{% for _, spec in each(portal.specs) %} +
  • {{spec.path}}
  • +{% end %} +``` +{% endraw %} + +Output: + +```hbs +
  • content/example1_spec.json
  • +
  • content/documentation/example1_spec.json
  • +``` + +**Filter by path** + +Template: + +{% raw %} +```hbs +{% for _, spec in each(helpers.filter_by_path(portal.specs, "content/documentation")) %} +
  • {{spec.path}}
  • +{% end %} +``` +{% endraw %} + +Output: + +```hbs +
  • content/documentation/example1_spec.json
  • +``` + +#### portal.developer_meta_fields + +Returns an array of developer meta fields available/required by Kong to register a developer. + +#### Return Type + +```lua +array +``` + +##### Usage + +**Printing a value** + +Template: + +{% raw %} +```hbs +{{ print(portal.developer_meta_fields) }} +``` +{% endraw %} + +Output: + +{% raw %} +```lua +{ + { + label = "Full Name", + name = "full_name", + type = "text", + required = true, + }, + ... +} +``` +{% endraw %} + +**Looping through values** + +Template: + +{% raw %} +```hbs +{% for i, field in each(portal.developer_meta_fields) do %} +
      +
    • Label: {{field.label}}
    • +
    • Name: {{field.name}}
    • +
    • Type: {{field.type}}
    • +
    • Required: {{field.required}}
    • +
    +{% end %} +``` +{% endraw %} + +Output: + +```html +
      +
    • Label: Full Name
    • +
    • Name: full_name
    • +
    • Type: text
    • +
    • Required: true
    • +
    +... +``` + +### page + +`page` gives access to data relating to the current page, which includes things like page url, path, breadcrumbs, and more. + + - [`page.route`](#pageroute) + - [`page.url`](#pageurl) + - [`page.breadcrumbs`](#pagebreadcrumbs) + - [`page.body`](#pagebody) + +When you create a new content page, you are able to define key-values. Here you are going to learn how to access those values and a few other interesting things. + +You can access the key-values you define directly on the `page` object like so: + +{% raw %} +```lua +page[key_name] or page.key_name +``` +{% endraw %} + +You can also access nested keys like so: + +```lua +page.key_name.nested_key +``` +{% raw %} +Be careful! To avoid output errors, make sure that the `key_name` exists before accessing `nested_key` as shown below: +```hbs +{{page.key_name and page.key_name.nested_key}} +``` +{% endraw %} + +#### page.route + +Returns the current page's route/path. + +##### Return Type + +```lua +string +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{page.route}} +``` +{% endraw %} + +Output, given url is `http://127.0.0.1:8003/default/guides/getting-started`: + +```html +guides/getting-started +``` + +#### page.url + +Returns the current page's url. + +##### Return Type + +```lua +string +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{page.url}} +``` +{% endraw %} + +Output, given url is `http://127.0.0.1:8003/default/guides/getting-started`: + +```html +http://127.0.0.1:8003/default/guides/getting-started +``` + +#### page.breadcrumbs + +Returns the current page's breadcrumb collection. + +##### Return Type + +```lua +table[] +``` + +##### Item Properties + +- `item.path` - Full path to item, no forward-slash prefix. +- `item.display_name` - Formatted name. +- `item.is_first` - Is this the first item in the list? +- `item.is_last` - Is this the last item in the list? + +##### Usage + +Template: + +{% raw %} +```hbs + +``` +{% endraw %} + +#### page.body + +Returns the body of the current page as a string. If the route's content file has a `.md` or `.markdown` extension, the body will be parsed from markdown to HTML. + +##### Return Type + +```lua +string +``` + +##### Usage for .txt, .json, .yaml, .yml templates + +`index.txt`: + +```hbs +This is text content. +``` + +Template: +{% raw %} +```hbs +

    This is a title

    +

    {{ page.body) }}

    +``` +{% endraw %} + +Output: +``` +> # This is a title +> This is text content. +``` + +##### Usage for .md, .markdown templates + +Template (markdown): +Use the raw delimiter syntax `{* *}` to render markdown within a template. + +`index.txt` +```hbs +# This is a title +This is text content. +``` + +Template: +```hbs +{* page.body *} +``` + +Output: +``` +> # This is a title +> This is text content. +``` + +### user + +`user` gives access to data relating to the currently authenticated user. User object is only applicable when `KONG_PORTAL_AUTH` is enabled. + + - [`user.is_authenticated`](#useris_authenticated) + - [`user.has_role`](#userhas_role) + - [`user.get`](#userget) + + +#### user.is_authenticated + +Returns `boolean` value as to the current user's authentication status. + +##### Return Type + +```lua +boolean +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{print(user.is_authenticated)}} +``` +{% endraw %} + +Output: + +```html +true +``` + +#### user.has_role + +Returns `true` if a user has a role given as an argument. + +##### Return Type + +```lua +boolean +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{print(user.has_role("blue"))}} +``` +{% endraw %} + +Output: + +```html +true +``` + +#### user.get + +Takes developer attribute as an argument and returns value if present. + +##### Return Type + +```lua +any +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{user.get("email")}} +{{print(user.get("meta"))}} +``` +{% endraw %} + +Output: + +```html +example123@konghq.com +{ "full_name" = "example" } +``` + + +### theme + +The `theme` object exposes values set in your `theme.conf.yaml` file. In addition, any variable overrides contained in `portal.conf.yaml` will be included as well. + + - [`theme.colors`](#usercolors) + - [`theme.color`](#usercolor) + - [`theme.fonts`](#userfonts) + - [`theme.font`](#userfont) + + +#### theme.colors + +Returns a table of color variables and their values as key-value pairs. + +##### Return Type + +```lua +table +``` + +##### Usage + +`theme.conf.yaml`: + +```yaml +name: Kong +colors: + primary: + value: '#FFFFFF' + description: 'Primary Color' + secondary: + value: '#000000' + description: 'Secondary Color' + tertiary: + value: '#1DBAC2' + description: 'Tertiary Color' +``` + +Template: + +{% raw %} +```lua +{% for k,v in each(theme.colors) do %} +

    {{k}}: {{v}}

    +{% end %} +``` +{% endraw %} + +Output: + +```html +

    primary: #FFFFFF

    +

    secondary: #000000

    +

    tertiary: #1DBAC2

    +``` + +#### theme.color + +Description + +Takes color var by string argument, returns value. + +##### Return Type + +```lua +string +``` + +##### Usage + +`theme.conf.yaml`: + +```yaml +name: Kong +colors: + primary: + value: '#FFFFFF' + description: 'Primary Color' + secondary: + value: '#000000' + description: 'Secondary Color' + tertiary: + value: '#1DBAC2' + description: 'Tertiary Color' +``` + +Template: + +{% raw %} +```lua +

    primary: {{theme.color("primary")}}

    +

    secondary: {{theme.color("secondary")}}

    +

    tertiary: {{theme.color("tertiary")}}

    +``` +{% endraw %} + +Output: + +```html +

    primary: #FFFFFF

    +

    secondary: #000000

    +

    tertiary: #1DBAC2

    +``` + + +#### theme.fonts + +Returns table of font vars and their values as key-value pairs. + +##### Return Type + +```lua +table +``` + +##### Usage + +`theme.conf.yaml`: + +```yaml +name: Kong +fonts: + base: Roboto + code: Roboto Mono + headings: Lato +``` + +Template: + +{% raw %} +```lua +{% for k,v in each(theme.fonts) do %} +

    {{k}}: {{v}}

    +{% end %} +``` +{% endraw %} + +Output: + +```html +

    base: Roboto

    +

    code: Roboto Mono

    +

    headings: Lato

    +``` + +#### theme.font + +Takes font name by string argument, returns value. + +##### Return Type + +```lua +string +``` + +##### Usage + +`theme.conf.yaml`: + +```yaml +name: Kong +fonts: + base: Roboto + code: Roboto Mono + headings: Lato +``` + +Template: + +{% raw %} +```lua +

    base: {{theme.font("base")}}

    +

    code: {{theme.font("code")}}

    +

    headings: {{theme.font("headings")}}

    +``` +{% endraw %} + +Output: + +```html +

    base: #FFFFFF

    +

    code: #000000

    +

    headings: #1DBAC2

    +``` + +### str + +Table containing useful string helper methods. + +#### Usage + +`.upper()` example: + +{% raw %} +```lua +
    {{ str.upper("dog") }}
    +``` +{% endraw %} + +#### Methods + +##### str.[byte](https://www.gammon.com.au/scripts/doc.php?lua=string.byte) +##### str.[char](https://www.gammon.com.au/scripts/doc.php?lua=string.char) +##### str.[dump](https://www.gammon.com.au/scripts/doc.php?lua=string.dump) +##### str.[find](https://www.gammon.com.au/scripts/doc.php?lua=string.find) +##### str.[format](https://www.gammon.com.au/scripts/doc.php?lua=string.format) +##### str.[gfind](https://www.gammon.com.au/scripts/doc.php?lua=string.gfind) +##### str.[gmatch](https://www.gammon.com.au/scripts/doc.php?lua=string.gmatch) +##### str.[gsub](https://www.gammon.com.au/scripts/doc.php?lua=string.gsub) +##### str.[len](https://www.gammon.com.au/scripts/doc.php?lua=string.len) +##### str.[lower](https://www.gammon.com.au/scripts/doc.php?lua=string.lower) +##### str.[match](https://www.gammon.com.au/scripts/doc.php?lua=string.match) +##### str.[rep](https://www.gammon.com.au/scripts/doc.php?lua=string.rep) +##### str.[reverse](https://www.gammon.com.au/scripts/doc.php?lua=string.reverse) +##### str.[sub](https://www.gammon.com.au/scripts/doc.php?lua=string.sub) +##### str.[upper](https://www.gammon.com.au/scripts/doc.php?lua=string.upper) +##### str.[isalpha](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isalpha) +##### str.[isdigit](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isdigit) +##### str.[isalnum](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isalnum) +##### str.[isspace](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isspace) +##### str.[islower](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#islower) +##### str.[isupper](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isupper) +##### str.[startswith](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#startswith) +##### str.[endswith](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#endswith) +##### str.[join](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#join) +##### str.[splitlines](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#splitlines) +##### str.[split](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#split) +##### str.[expandtabs](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#expandtabs) +##### str.[lfind](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#lfind) +##### str.[rfind](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#rfind) +##### str.[replace](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#replace) +##### str.[count](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#count) +##### str.[ljust](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#ljust) +##### str.[rjust](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#rjust) +##### str.[center](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#center) +##### str.[lstrip](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#lstrip) +##### str.[rstrip](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#rstrip) +##### str.[strip](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#strip) +##### str.[splitv](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#splitv) +##### str.[partition](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#partition) +##### str.[rpartition](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#rpartition) +##### str.[at](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#at) +##### str.[lines](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#lines) +##### str.[title](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#title) +##### str.[shorten](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#shorten) +##### str.[quote_string](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#quote_string) + + +### tbl + +Table containing useful table helper methods + +#### Usage + +`.map()` example: +{% raw %} +```lua +{% tbl.map({"dog", "cat"}, function(item) %} + {% if item ~= "dog" then %} + {% return true %} + {% end %} +{% end) %} +``` +{% endraw %} + +#### Methods + +##### tbl.[getn](https://www.gammon.com.au/scripts/doc.php?lua=table.getn) +##### tbl.[setn](https://www.gammon.com.au/scripts/doc.php?lua=table.setn) +##### tbl.[maxn](https://www.gammon.com.au/scripts/doc.php?lua=table.maxn) +##### tbl.[insert](https://www.gammon.com.au/scripts/doc.php?lua=table.insert) +##### tbl.[remove](https://www.gammon.com.au/scripts/doc.php?lua=table.remove) +##### tbl.[concat](https://www.gammon.com.au/scripts/doc.php?lua=table.concat) +##### tbl.[map](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#map) +##### tbl.[foreach](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#foreach) +##### tbl.[foreachi](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#foreachi) +##### tbl.[sort](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#sort) +##### tbl.[sortv](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#sortv) +##### tbl.[filter](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#filter) +##### tbl.[size](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#size) +##### tbl.[index_by](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#index_by) +##### tbl.[transform](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#transform) +##### tbl.[range](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#range) +##### tbl.[reduce](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#reduce) +##### tbl.[index_map](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#index_map) +##### tbl.[makeset](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#makeset) +##### tbl.[union](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#union) +##### tbl.[intersection](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#intersection) +##### tbl.[count_map](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#count_map) +##### tbl.[set](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#set) +##### tbl.[new](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#new) +##### tbl.[clear](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#clear) +##### tbl.[removevalues](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#removevalues) +##### tbl.[readonly](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#readonly) +##### tbl.[update](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#update) +##### tbl.[copy](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#copy) +##### tbl.[deepcopy](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#deepcopy) +##### tbl.[icopy](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#icopy) +##### tbl.[move](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#move) +##### tbl.[insertvalues](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#insertvalues) +##### tbl.[deepcompare](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#deepcompare) +##### tbl.[compare](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#compare) +##### tbl.[compare_no_order](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#compare_no_order) +##### tbl.[find](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#find) +##### tbl.[find_if](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#find_if) +##### tbl.[search](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#search) +##### tbl.[keys](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#keys) +##### tbl.[values](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#values) +##### tbl.[sub](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#sub) +##### tbl.[merge](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#merge) +##### tbl.[difference](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#difference) +##### tbl.[zip](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#zip) + \ No newline at end of file diff --git a/app/gateway/2.6.x/get-started/comprehensive/dev-portal.md b/app/gateway/2.6.x/get-started/comprehensive/dev-portal.md new file mode 100644 index 000000000000..aacfac2ebd9e --- /dev/null +++ b/app/gateway/2.6.x/get-started/comprehensive/dev-portal.md @@ -0,0 +1,100 @@ +--- +title: Publish, Locate, and Consume Services +badge: enterprise +--- + +Dev Portal provides a single source of truth for all developers to locate, access, and consume services. With intuitive content management for documentation, streamlined developer onboarding, and role-based access control (RBAC), the Dev Portal provides a comprehensive solution for creating and customizing a unified developer experience. + +## Before you begin + +Make sure the Dev Portal is on. You should have enabled it during [installation](/gateway/{{page.release}}/install-and-run/). + +## Enable the Dev Portal for a Workspace + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. In Kong Manager, open the Workspaces tab and open your workspace (for example, SecureWorkspace). + +2. Scroll down in the sidebar, then click the **Overview** link under the Dev Portal section. + +3. Click **Enable Developer Portal** and refresh the browser page. + +{% endnavtab %} +{% navtab Using the Admin API %} + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X PATCH http://localhost:8001/workspaces/SecureWorkspace \ + --data config.portal=true +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f PATCH http://localhost:8001/workspaces/SecureWorkspace \ + config.portal=true +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% endnavtabs %} +This will expose the Dev Portal at `http://localhost:8003/SecureWorkspace.` + +After the Dev Portal is enabled for the Workspace, a few new links appear in the left navigation menu. It may take a few seconds for the Settings page to populate. + +You can learn more about personalization in the [Dev Portal documentation](/gateway/{{page.release}}/developer-portal/), including: + +* [Customizing the look and feel of the site and editor](/gateway/{{page.release}}/developer-portal/theme-customization/easy-theme-editing/) +* [Managing access](/gateway/{{page.release}}/developer-portal/administration/managing-developers/) +* [Configuring the Dev Portal](/gateway/{{page.release}}/developer-portal/configuration/workspaces/) + +## Access and Interact with the Dev Portal + +1. Go back to **Dev Portal** > **Overview** and open the link in a new tab, or open the Dev Portal directly using this URL: `http://localhost:8003/SecureWorkspace`. + + You’ll see a list of available API catalogs. By default, *httpbin.org* and *Swagger Petstore* appear as examples. + +2. Click on the **httpbin.org** entry to explore the API. + + On the left side, tags for the API as configured by the spec are displayed for easy searching. + + On the right, you can see the HTTP methods of the API. Clicking into each method shows its details, lets you test the method, and provides code snippets developers can use to leverage the method in their applications. + +3. Test the GET method: + + 1. Under **HTTP Methods**, click the GET method. + 2. Click **Try it Out**, then click **Execute**. Review the results of the response. + +## Publish a Spec to Dev Portal + +In this section, you’re going to add a new spec, the *Kong Vitals API*, to the Dev Portal catalog. The Kong Vitals API shows how {{site.base_gateway}} and connected APIs are performing. + +1. In Kong Manager, navigate to **Dev Portal** > **Editor** and open the link in a new tab. The editor lets you customize the Dev Portal. + +2. Click on **New File +** to add a new spec. + +3. In the New File dialog, open the dropdown and select **spec**, then name the spec `vitals_spec.yaml`. + +4. Click on **Create File**. + + The editor creates the file and prepares it for editing. Since you haven’t added any content to the file, the preview displays “Unable to render this definition”. + +5. In another tab, open the [Kong Vitals Overview page](/gateway/{{page.release}}/vitals/#using-vitals-api) to download the `vitalsSpec.yaml.` Open it in your favorite text editor and copy the contents of the file. + +6. In the Dev Portal editor, clear the contents of the editor, then paste the contents of `vitalsSpec.yaml`. + +7. Click **Save Changes**. If done correctly, the preview should show the API now. + +8. View the Dev Portal at `http://localhost:8003/SecureWorkspace` and notice the new spec published to the Dev Portal. + +## Summary + +In this topic, you: + +* Enabled the Dev Portal on the Workspace `SecureWorkspace`. +* Tested the httpbin `GET` method. +* Added a new spec for the Kong Vitals API to the Dev Portal catalog. diff --git a/app/gateway/2.6.x/get-started/comprehensive/expose-services.md b/app/gateway/2.6.x/get-started/comprehensive/expose-services.md new file mode 100644 index 000000000000..d36ae859bea1 --- /dev/null +++ b/app/gateway/2.6.x/get-started/comprehensive/expose-services.md @@ -0,0 +1,332 @@ +--- +title: Expose your Services with Kong Gateway +--- + +In this topic, you’ll learn how to expose your Services using Routes. + +If you are following the Getting Started workflow, make sure you have completed +[Prepare to Administer {{site.base_gateway}}](/gateway/{{page.release}}/get-started/comprehensive/prepare) +before moving on. + +If you are not following the Getting Started workflow, make sure you have +{{site.base_gateway}} installed and started. + +## What are Services and Routes? + +**Service** and **Route** objects let you expose your services to clients with +{{site.base_gateway}}. When configuring access to your API, you’ll start by specifying a +Service. In {{site.base_gateway}}, a Service is an entity representing an external +upstream API or microservice — for example, a data transformation +microservice, a billing API, and so on. + +The main attribute of a Service is its **URL**, where the service listens for +requests. You can specify the URL with a single string, or by specifying its +protocol, host, port, and path individually. + +Before you can start making requests against the Service, you will need to add +a Route to it. Routes determine how (and if) requests are sent to their Services +after they reach {{site.base_gateway}}. A single Service can have many Routes. + +After configuring the Service and the Route, you’ll be able to start making +requests through {{site.base_gateway}}. + +This diagram illustrates the flow of requests and responses being routed through +the Service to the backend API. + +![Services and routes](/assets/images/products/gateway/getting-started-guide/route-and-service.png) + +## Add a Service + +For the purpose of this example, you’ll create a Service pointing to the httpbin +API. Httpbin is an “echo” type public website that returns requests back to the +requester as responses. This visualization will be helpful for learning how Kong +Gateway proxies API requests. + +{{site.base_gateway}} exposes the RESTful Admin API on port `8001`. The gateway’s +configuration, including adding Services and Routes, is done through requests to +the Admin API. + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. On the Workspaces tab in Kong Manager, scroll to the Workspace section and +click the **default** workspace. + + This example uses the default workspace, but you can also create a new + workspace, or use an existing workspace. + +2. Scroll down to **Services** and click **Add a Service**. + +3. In the **Create Service** dialog, enter the name `example_service` and the +URL `https://httpbin.konghq.com`. + +4. Click **Create**. + +The service is created, and the page automatically redirects back to the +`example_service` overview page. +{% endnavtab %} +{% navtab Using the Admin API %} + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/services \ + --data name=example_service \ + --data url='https://httpbin.konghq.com' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http POST :8001/services \ + name=example_service \ + url='https://httpbin.konghq.com' +``` +{% endnavtab %} +{% endnavtabs %} + + +If the service is created successfully, you'll get a 201 success message. + +Verify the service’s endpoint: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i http://localhost:8001/services/example_service +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/services/example_service +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +1. In the `kong.yaml` file you exported in +[Prepare to Administer {{site.base_gateway}}](/gateway/{{page.release}}/get-started/comprehensive/prepare/#verify-the-kong-gateway-configuration), +define a Service with the name `example_service` and the URL +`https://httpbin.konghq.com`: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + ``` +2. Save the file. From your terminal, sync the configuration to update your +gateway instance: + + ``` bash + deck sync + ``` + + The message should show that you’re creating a service: + + ``` + creating service example_service + Summary: + Created: 1 + Updated: 0 + Deleted: 0 + ``` + +{% endnavtab %} +{% endnavtabs %} + +## Add a Route + +For the Service to be accessible through the API gateway, you need to add a +Route to it. + +{% navtabs %} +{% navtab Using Kong Manager %} +1. From the `example_service` overview page, scroll down to the Routes section +and click **Add Route**. + + The Create Route dialog displays with the Service field auto-populated with + the Service name and ID number. This field is required. + + **Note:** If the Service field is not automatically populated, click + **Services** in the left navigation pane. Find your Service, click the + clipboard icon next to the id field, then go back to the Create Route + page and paste it into the Service field. + +2. Enter a name for the Route, and at least one of the following fields: Host, +Methods, or Paths. For this example, use the following: + 1. For **Name**, enter `mocking`. + 2. For **Path(s)**, click **Add Path** and enter `/mock`. + +3. Click **Create**. + +The Route is created and you are automatically redirected back to the +`example_service` overview page. The new Route appears under the Routes section. + +{% endnavtab %} +{% navtab Using the Admin API %} + +Define a Route (`/mock`) for the Service (`example_service`) with a specific +path that clients need to request. Note at least one of the hosts, paths, or +methods must be set for the Route to be matched to the service. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/services/example_service/routes \ + --data 'paths[]=/mock' \ + --data name=mocking +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/services/example_service/routes \ + paths:='["/mock"]' \ + name=mocking +``` +{% endnavtab %} +{% endnavtabs %} + + +A `201` message indicates the Route was created successfully. + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +1. Paste the following into the `kong.yaml` file, under the entry for +`example_service`: + + ``` yaml + routes: + - name: mocking + paths: + - /mock + strip_path: true + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + ``` + +2. Sync the configuration: + + ``` bash + deck sync + ``` + +3. (Optional) You can update your local file with the new configuration: + + {:.important} + > **Be careful!** Any subsequent `deck dump` will + overwrite the existing `kong.yaml` file. Create backups as needed. + + ``` bash + $ deck dump + ``` + + Alternatively, you will also see this configuration in the diff that decK + shows when you're syncing a change to the configuration. + + You'll notice that both the Service and Route now have parameters that you + did not explicitly set. These are default parameters that every Service and + Route are created with: + + ``` yaml + services: + - connect_timeout: 60000 + host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 + routes: + - name: mocking + paths: + - /mock + path_handling: v0 + preserve_host: false + protocols: + - http + - https + regex_priority: 0 + strip_path: true + https_redirect_status_code: 426 + ``` + + You can do this after any `deck sync` to see {{site.base_gateway}}'s most + recent configuration. + + The rest of this guide continues using the simplified version of the + configuration file without performing a `deck dump` for every step, to keep + it easy to follow. + +{% endnavtab %} +{% endnavtabs %} + +## Verify the Route is forwarding requests to the Service + +{% navtabs %} +{% navtab Using a Web Browser %} + +By default, {{site.base_gateway}} handles proxy requests on port `:8000`. + +From a web browser, enter `http://localhost:8000/mock`. + +{% endnavtab %} +{% navtab Using the Admin API %} + +Using the Admin API, issue the following: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X GET http://localhost:8000/mock/anything +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock/anything +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% endnavtabs %} + + +## Summary and next steps + +In this section, you: + +* Added a Service named `example_service` with a URL of `https://httpbin.konghq.com`. +* Added a Route named `/mock`. +* This means if an HTTP request is sent to the {{site.base_gateway}} node on +port `8000`(the proxy port) and it matches route `/mock`, then that request is +sent to `https://httpbin.konghq.com`. +* Abstracted a backend/upstream service and put a route of your choice on the +front end, which you can now give to clients to make requests. + +Next, go on to learn about [enforcing rate limiting](/gateway/{{page.release}}/get-started/comprehensive/protect-services/). diff --git a/app/gateway/2.6.x/get-started/comprehensive/improve-performance.md b/app/gateway/2.6.x/get-started/comprehensive/improve-performance.md new file mode 100644 index 000000000000..23d1f59e948e --- /dev/null +++ b/app/gateway/2.6.x/get-started/comprehensive/improve-performance.md @@ -0,0 +1,200 @@ +--- +title: Improve Performance with Proxy Caching +--- + +In this topic, you’ll learn how to use proxy caching to improve response efficiency using the Proxy Caching plugin. + +If you are following the getting started workflow, make sure you have completed [Protect your Services](/gateway/{{page.release}}/get-started/comprehensive/protect-services/) before continuing. + +## What is Proxy Caching? + +{{site.base_gateway}} delivers fast performance through caching. The Proxy Caching plugin provides this fast performance using a reverse proxy cache implementation. It caches response entities based on the request method, configurable response code, content type, and can cache per Consumer or per API. + +Cache entities are stored for a configurable period of time. When the timeout is reached, the gateway forwards the request to the Upstream, caches the result and responds from cache until the timeout. The plugin can store cached data in memory, or for improved performance, in Redis. + +## Why use Proxy Caching? + +Use proxy caching so that Upstream services are not bogged down with repeated requests. With proxy caching, {{site.base_gateway}} can respond with cached results for better performance. + +## Set up the Proxy Caching plugin + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Access your Kong Manager instance and your **default** workspace. + +2. Go to **API Gateway** and click **Plugins**. + +3. Click **New Plugin**. + +4. Scroll down to the Traffic Control section and find the **Proxy Caching** plugin. + +5. Click **Enable**. + +6. Select to apply the plugin as **Global**. This means that proxy caching applies to all requests. + +7. Scroll down and complete only the following fields with the parameters listed. + 1. config.cache_ttl: `30` + 2. config.content_type: `application/json; charset=utf-8` + 3. config.strategy: `memory` + + Besides the above fields, there may be others populated with default values. For this example, leave the rest of the fields as they are. + +8. Click **Create**. +{% endnavtab %} +{% navtab Using the Admin API %} + +Call the Admin API on port `8001` and configure plugins to enable in-memory caching globally, with a timeout of 30 seconds for Content-Type `application/json`. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/plugins \ + --data name=proxy-cache \ + --data config.content_type="application/json; charset=utf-8" \ + --data config.cache_ttl=30 \ + --data config.strategy=memory +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/plugins \ + name=proxy-cache \ + config.strategy=memory \ + config.cache_ttl=30 \ + config.content_type="application/json; charset=utf-8" +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +1. In the `plugins` section of your `kong.yaml` file, add the `proxy-cache` +plugin with a timeout of 30 seconds for Content-Type +`application/json; charset=utf-8`. + + ``` yaml + plugins: + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + +2. Sync the configuration: + + ```bash + deck sync + ``` + +{% endnavtab %} +{% endnavtabs %} + + +## Validate Proxy Caching + +Let’s check that proxy caching works. You'll need the Kong Admin API for this +step. + +Access the */mock* route using the Admin API and note the response headers: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X GET http://localhost:8000/mock/anything +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock/anything +``` +{% endnavtab %} +{% endnavtabs %} + + +In particular, pay close attention to the values of `X-Cache-Status`, `X-Kong-Proxy-Latency`, and `X-Kong-Upstream-Latency`: +``` +HTTP/1.1 200 OK +... +X-Cache-Key: d2ca5751210dbb6fefda397ac6d103b1 +X-Cache-Status: Miss +X-Content-Type-Options: nosniff +... +X-Kong-Proxy-Latency: 25 +X-Kong-Upstream-Latency: 37 +``` + +Next, access the */mock* route one more time. + +This time, notice the differences in the values of `X-Cache-Status`, `X-Kong-Proxy-Latency`, and `X-Kong-Upstream-Latency`. Cache status is a `hit`, which means {{site.base_gateway}} is responding to the request directly from cache instead of proxying the request to the Upstream service. + +Further, notice the minimal latency in the response, which allows {{site.base_gateway}} to deliver the best performance: + +``` +HTTP/1.1 200 OK +... +X-Cache-Key: d2ca5751210dbb6fefda397ac6d103b1 +X-Cache-Status: Hit +... +X-Kong-Proxy-Latency: 0 +X-Kong-Upstream-Latency: 1 +``` + +To test more rapidly, the cache can be deleted by calling the Admin API: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X DELETE http://localhost:8001/proxy-cache +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http delete :8001/proxy-cache +``` +{% endnavtab %} +{% endnavtabs %} + + +## Summary and Next Steps + +In this section, you: + +* Set up the Proxy Caching plugin, then accessed the `/mock` route multiple times to see caching in effect. +* Witnessed the performance differences in latency with and without caching. + +Next, you’ll learn about [securing services](/gateway/{{page.release}}/get-started/comprehensive/secure-services/). diff --git a/app/gateway/2.6.x/get-started/comprehensive/index.md b/app/gateway/2.6.x/get-started/comprehensive/index.md new file mode 100644 index 000000000000..d56aa0d59208 --- /dev/null +++ b/app/gateway/2.6.x/get-started/comprehensive/index.md @@ -0,0 +1,109 @@ +--- +title: Comprehensive Getting Started Guide +--- + +In this guide, you will: + +* Expose your services using Service and Route objects +* Set up rate limits and proxy caching +* Secure services with key authentication +* Load balance traffic + +If you have a license, you also have access +to Enterprise features. In addition to the basics above, +use this guide to: + +* Manage teams by setting up role-based access control (RBAC) +* Enable the Dev Portal to give your teams a central location to +publish, access, and consume services + +**{{site.ce_product_name}}**: an open-source, lightweight API gateway optimized +for microservices, delivering unparalleled latency, performance, and scalability. + If you just want the basics, this option will work for you. + +**{{site.base_gateway}}**: extends the {{site.base_gateway}} with Enterprise +features and support. It provides advanced functionality using plugins for +security, collaboration, performance at scale, and use of advanced protocols. + +## Concepts and Features in this guide + +Here’s the content covered in this guide, and how the pieces fit together: + +![Features in getting started guide](/assets/images/products/gateway/getting-started-guide/Kong-GS-overview.png) + +| Concept/Feature | Description {:width=75%:} | +|:------------------ |:--------------------------| +| Service | A Service object is the ID {{site.base_gateway}} uses to refer to the upstream APIs and microservices it manages. | +| Routes | Routes specify how (and if) requests are sent to their Services after they reach the API gateway. A single Service can have many Routes. | +| Consumers | Consumers represent end users of your API. Consumer objects let you control who can access your APIs. They also let you report on traffic using logging plugins and Kong Vitals. | +| Kong Manager | Kong Manager is the visual browser-based tool for monitoring and managing {{site.ee_product_name}}. | +| Admin API | {{site.base_gateway}} comes with an internal RESTful API for administration purposes. API commands can be run on any node in the cluster, and the configuration will apply consistently on all nodes. | +| Plugins | Plugins provide a modular system for modifying and controlling {{site.base_gateway}}’s capabilities. For example, to secure your API, you could require an access key, which you could set up using the key-auth plugin. Plugins provide a wide array of functionality, including access control, caching, rate limiting, logging, and more. | +| Rate Limiting plugin

    Rate Limiting Advanced plugin | This plugin lets you limit the number of HTTP requests a client can make within a given period of time.

    The advanced version of this plugin also provides sliding window support, and the ability to limit by header and service. | +| Proxy Caching plugin

    Proxy Caching Advanced plugin | This plugin provides a reverse proxy cache implementation. It caches response entities based on response code, content type, and request method for a given period of time.

    The advanced version of this plugin supports Redis and Redis Sentinel deployments. | +| Key Auth plugin

    Key Auth - Encrypted plugin | This plugin lets you add key authentication (also known as an API key) to a Service or a Route.

    The advanced version of this plugin stores the API keys in an encrypted format within the {{site.base_gateway}} data store. | +| Load Balancing | {{site.base_gateway}} provides two methods for load balancing: straightforward DNS-based or using a ring-balancer. In this guide, you’ll use a ring-balancer, which requires configuring upstream and target entities. With this method, the adding and removing of backend services is handled by {{site.base_gateway}}, and no DNS updates are necessary. | +| User Authorization (RBAC) | {{site.base_gateway}} handles user authorization through role-based access control (RBAC). Once enabled, RBAC lets you create teams and admins and assign them granular permissions either within a workspace, or across workspaces. | +| Dev Portal | The Dev Portal provides a single source of truth for all developers to locate, access, and consume services. | + + +## Understanding traffic flow in {{site.base_gateway}} + +{{site.base_gateway}} listens for traffic on its configured proxy port(s) `8000` +and `8443`, by default. It evaluates incoming client API requests and routes them +to the appropriate backend APIs. While routing requests and providing responses, +policies can be applied via plugins as necessary. + +For example, before routing a request, the client might be required to +authenticate. This delivers several benefits, including: + +* The service doesn’t need its own authentication logic since +{{site.base_gateway}} is handling authentication. +* The service only receives valid requests and therefore cycles are not wasted +processing invalid requests. +* All requests are logged for central visibility of traffic. + +![API Gateway traffic](/assets/images/products/gateway/getting-started-guide/gateway-traffic.png) + +## Before you begin + +Note the following before you start using this guide: + +### Installation + +* This guide assumes that you have {{site.ce_product_name}} +or {{site.base_gateway}} +[installed and running](/gateway/{{page.release}}/install-and-run/) on the platform of your choice. +* During your installation, take note of the `KONG_PASSWORD`; you’ll need it +later on in this guide for setting up user authorization. + +### Deployment guidelines + +* You can use this guide to get started in production environments, but this +guide does not provide all of the necessary configurations and security settings +that you would need for a production environment. +* The examples in this guide all use `` to refer to a +{{site.base_gateway}} instance's Admin API URL. Make sure to replace the +variable with the actual URL of your {{site.base_gateway}} installation. + + To find the URL, check the `admin_listen` property in the + `/etc/kong/kong.conf` file. + +### Using this guide + +* Throughout this guide, you will have the option to configure Kong in a few +different ways. Choose your preferred method, if options are available — +you don’t have to walk through all of them: + * Programmatically manage {{site.base_gateway}} using its REST-based Admin API + * Use the Kong Manager GUI *(Not available for open-source Gateway)* + * Use decK for declarative configuration (YAML) +* If you're running {{site.base_gateway}} in Hybrid mode, all tasks contained +in this guide take place on the Control Plane. +* This guide provides Kong Admin API examples in both HTTPie and cURL. If you +want to use HTTPie, install it from [here](https://httpie.org/). +* Any references to “{{site.base_gateway}}” refer to features or concepts +common to both {{site.ce_product_name}} and {{site.base_gateway}}. + +### Next Steps + +Next, [prepare to administer {{site.base_gateway}}](/gateway/{{page.release}}/get-started/comprehensive/prepare/). diff --git a/app/gateway/2.6.x/get-started/comprehensive/load-balancing.md b/app/gateway/2.6.x/get-started/comprehensive/load-balancing.md new file mode 100644 index 000000000000..b36c39acd2f7 --- /dev/null +++ b/app/gateway/2.6.x/get-started/comprehensive/load-balancing.md @@ -0,0 +1,199 @@ +--- +title: Set Up Intelligent Load Balancing +--- + +In this topic, you’ll learn about configuring upstream services, and create multiple targets for load balancing. + +If you are following the getting started workflow, make sure you have completed [Secure Services Using Authentication](/gateway/{{page.release}}/get-started/comprehensive/secure-services/) before moving on. + +## What are Upstreams? + +An **Upstream Object** refers to your upstream API/service sitting behind {{site.base_gateway}}, to which client requests are forwarded. In {{site.base_gateway}}, an Upstream Object represents a virtual hostname and can be used to health check, circuit break, and load balance incoming requests over multiple services (targets). + +In this topic, you’ll configure the service created earlier (`example_service`) to point to an upstream instead of the host. For the purposes of our example, the upstream will point to two different targets, `httpbin.konghq.com` and `httpbun.com`. In a real environment, the upstream will point to the same service running on multiple systems. + +Here is a diagram illustrating the setup: + +![Upstream targets](/assets/images/products/gateway/getting-started-guide/upstream-targets.png) + +## Why load balance across upstream targets? + +In the following example, you’ll use an application deployed across two different servers, or upstream targets. {{site.base_gateway}} needs to load balance across both servers, so that if one of the servers is unavailable, it automatically detects the problem and routes all traffic to the working server. + +## Configure Upstream Services + +In this section, you will create an Upstream named `example_upstream` and add two targets to it. + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Access your Kong Manager instance and your **default** workspace. +2. Go to **API Gateway** > **Upstreams**. +3. Click **New Upstream**. +4. For this example, enter `example_upstream` in the **Name** field. +5. Scroll down and click **Create**. +6. On the Upstreams page, find the new upstream service and click **View**. +7. Scroll down and click **New Target**. +8. In the target field, specify `httpbin.konghq.com` with port `80`, and click **Create**. +9. Create another target, this time for `httpbun.com` with port `80`. Click **Create**. +10. Open the **Services** page. +11. Find your `example_service` and click **Edit**. +12. Change the **Host** field to `example_upstream`, then click **Update**. +{% endnavtab %} +{% navtab Using the Admin API %} + +Call the Admin API on port `8001` and create an Upstream named `example_upstream`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/upstreams \ + --data name=example_upstream +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http POST :8001/upstreams \ + name=example_upstream +``` +{% endnavtab %} +{% endnavtabs %} + + +Update the service you created previously to point to this upstream: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X PATCH http://localhost:8001/services/example_service \ + --data host='example_upstream' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http PATCH :8001/services/example_service \ + host='example_upstream' +``` +{% endnavtab %} +{% endnavtabs %} + + +Add two targets to the upstream, each with port 80: `httpbun.com:80` and +`httpbin.konghq.com:80`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/upstreams/example_upstream/targets \ + --data target='httpbun.com:80' + +curl -X POST http://localhost:8001/upstreams/example_upstream/targets \ + --data target='httpbin.konghq.com:80' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http POST :8001/upstreams/example_upstream/targets \ + target=httpbun.com:80 +http POST :8001/upstreams/example_upstream/targets \ + target=httpbin.konghq.com:80 +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} + +{% navtab Using decK (YAML) %} +1. In your `kong.yaml` file, create an Upstream with two targets, each with port +80: `httpbun.com:80` and `httpbin.konghq.com:80`. + + ``` yaml + upstreams: + - name: example_upstream + targets: + - target: httpbin.konghq.com:80 + weight: 100 + - target: httpbun.com:80 + weight: 100 + ``` + +2. Update the service you created previously, pointing the `host` to this +Upstream: + + ``` yaml + services: + host: example_upstream + name: example_service + port: 80 + protocol: http + ``` + + After these updates, your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: example_upstream + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: key-auth + enabled: false + consumers: + - custom_id: consumer + username: consumer + keyauth_credentials: + - key: apikey + upstreams: + - name: example_upstream + targets: + - target: httpbin.konghq.com:80 + weight: 100 + - target: httpbun.com:80 + weight: 100 + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + +3. Sync the configuration: + + ``` bash + deck sync + ``` +{% endnavtab %} +{% endnavtabs %} + +You now have an Upstream with two targets, `httpbin.konghq.com` and `httpbun.com`, and a service pointing to that Upstream. + +## Validate the Upstream Services + +1. With the Upstream configured, validate that it’s working by visiting the route `http://localhost:8000/mock` using a web browser or CLI. +2. Continue hitting the endpoint and the site should change from `httpbin` to `httpbun`. + +## Summary and next steps + +In this topic, you: + +* Created an Upstream object named `example_upstream` and pointed the Service `example_service` to it. +* Added two targets, `httpbin.konghq.com` and `httpbun.com`, with equal weight to the Upstream. + +If you have a {{site.konnect_product_name}} subscription, go on to [Managing Administrative Teams](/gateway/{{page.release}}/get-started/comprehensive/manage-teams/). diff --git a/app/gateway/2.6.x/get-started/comprehensive/manage-teams.md b/app/gateway/2.6.x/get-started/comprehensive/manage-teams.md new file mode 100644 index 000000000000..fb49573abffe --- /dev/null +++ b/app/gateway/2.6.x/get-started/comprehensive/manage-teams.md @@ -0,0 +1,367 @@ +--- +title: Manage Administrative Teams +badge: enterprise +--- + +In this topic, you’ll learn how to manage and configure user authorization using workspaces and teams in {{site.base_gateway}}. + +If you are following the getting started workflow, make sure you have completed [Set Up Intelligent Load Balancing](/gateway/{{page.release}}/get-started/comprehensive/load-balancing/) before moving on. + +## Overview of workspaces and Teams + +Many organizations have strict security requirements. For example, organizations need the ability to segregate the duties of an administrator to ensure that a mistake or malicious act by one administrator doesn’t cause an outage. {{site.base_gateway}} provides a number of security capabilities to help customers secure the administration environment. + +**Workspaces** enable an organization to segment objects and admins into namespaces. The segmentation allows teams of admins sharing the same {{site.base_gateway}} cluster to adopt **roles** for interacting with specific objects. For example, one team (Team A) may be responsible for managing a particular service, whereas another team (Team B) may be responsible for managing another service. Teams should only have the roles they need to perform the administrative tasks within their specific workspaces. + +{{site.base_gateway}} does all of this through **Role-Based Access Control (RBAC)**. All administrators can be given specific roles, whether you are using Kong Manager or the Admin API, which control and limit the scope of administrative privileges within specific workspaces. + +In this example, you’ll start by creating a simple workspace called `SecureWorkspace`. Then, you’ll create an administrator for that workspace, with rights to administer only the objects in the SecureWorkspace and nothing else. + +>**Note:** The steps in this topic cannot be performed using declarative +configuration. + +## Securing your Gateway Installation + +At a high level, securing {{site.base_gateway}} administration is a two-step process: + +1. Turn on RBAC. +2. Create a workspace and an admin for segregated administration. + +At this point in the Getting Started Guide, you have been interacting with your environment as the built-in Super Admin, `kong_admin`. The password for this `kong_admin` user was “seeded” during the installation process using the KONG_PASSWORD environment variable. After RBAC is enabled, you will need to authenticate to the Kong Manager and the {{site.base_gateway}} Admin API using the proper credentials. + +In the following sections, you will need the `kong_admin` account’s password to log in to {{site.base_gateway}}, and the `kong_admin_uri` needs to be configured to avoid getting CORS errors. + +## Turn on RBAC + +{% include_cached /md/enterprise/turn-on-rbac.md %} + +## Create a workspace + +{% navtabs %} +{% navtab Using Kong Manager %} + +### Log into Kong Manager + +1. Go to Kong Manager, or reload the page if you already have it open and you will see the following login screen. +2. Log in to Kong Manager with the built-in Super Admin account, `kong_admin`, and its password. + + Remember, this is the initial KONG_PASSWORD you used when you ran migrations during installation. + +3. If you have logged in successfully, then you can start administering your {{site.base_gateway}} cluster. + + If this step did not work, and you know the credentials are correct, then something is likely wrong with your {{site.base_gateway}} configuration. Double-check the settings. If the cause of the problem still isn’t clear, work with your {{site.konnect_product_name}} account team and [Kong Support](https://support.konghq.com/) for assistance. + +#### Create the Workspace + +1. Access your Kong Manager instance. +2. On the workspaces tab, click on **New Workspace**. +3. Create a workspace named `SecureWorkspace` and select a color for the workspace avatar. + + **Note:** Each workspace name should be unique, regardless of letter case. For example, naming one workspace “Payments” and another one “payments” will create two different workspaces that appear identical. + + **WARNING:** Do not give a workspace the same name as any of these major routes in Kong Manager: + + |---------|-----------|--------------|---------------| + | Admins | APIs | Certificates | Consumers | + | Plugins | Portal | Routes | Services | + | SNIs | Upstreams | Vitals | PermalinkStep | + +4. Click **Create New workspace**. +5. On the new workspace, click **Teams**. +6. From the Teams page, click the **Roles** tab to view the default roles that come with {{site.base_gateway}}. +7. Next to SecureWorkspace, click **View** to see its assigned roles. +8. There are different roles available for the SecureWorkspace. By default, each new workspace has the following roles and privileges: + + | Role | Description | + |--------------------------|----------------------------------------------------------------------------------------------| + | *workspace-admin* | Can administer the objects in a workspace but can’t add new administrators to the workspace. | + | *workspace-portal-admin* | Can manage the Dev Portal. | + | *workspace-read-only* | Can view anything in the workspace, but can’t make any changes. | + | *workspace-super-admin* | Can do anything inside the workspace. | + +**Notes:** + +* **Be careful:** Granting access to the **default** workspace gives access to all workspaces in the organization. + +* The **default** workspace only has three roles: *workspace-admin*, *workspace-super admin*, and *workspace-read-only*. Every other workspace will have the four roles mentioned above. + +* You can also create custom roles by clicking on the **Add Role** button and specifying the endpoints that the administrator with the role will be able to interact with. +{% endnavtab %} +{% navtab Using the Admin API %} +Create a new workspace called SecureWorkspace, substituting the `kong_admin` +account’s password in place of ``: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/workspaces \ + -H Kong-Admin-Token: \ + --data 'name=SecureWorkspace' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/workspaces \ + name=SecureWorkspace \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +**Note:** Each workspace name should be unique, regardless of letter case. For example, naming one workspace “Payments” and another one “payments” will create two different workspaces that appear identical. + +**WARNING:** +* Granting access to the **default** workspace gives access to all workspaces in the organization. +* Do not give a workspace the same name as any of these major routes in Kong Manager: + + |---------|-----------|--------------|---------------| + | Admins | APIs | Certificates | Consumers | + | Plugins | Portal | Routes | Services | + | SNIs | Upstreams | Vitals | PermalinkStep | + +If you are unable to log in with `kong_admin`'s token, and you know the credentials are correct, then something is likely wrong with your {{site.base_gateway}} configuration. Double-check the settings, or, if the cause of the problem still isn’t clear, work with your {{site.konnect_product_name}} account team and Kong support for assistance. + +{% endnavtab %} +{% endnavtabs %} + +## Create an Admin + +Next, create an admin for the SecureWorkspace, granting them permissions to manage only that workspace. + +{% navtabs %} +{% navtab Using Kong Manager %} +### Invite a New Admin + +{:.note} +> If you also use the Admin API, once you've created this admin, you can find it under the `/admins` endpoint. + +1. From the **Teams** > **Admins** tab, click **Invite Admin**. +2. Enter the new administrator’s **Email** address, **Username**, and **Custom Id**. +3. Ensure that **Enable RBAC Token** is enabled. + + **Note:** This setting lets the admin use the Admin API as well as Kong Manager. If you don’t want this user to access the Admin API, uncheck this box. + +4. Click **Add/Edit Roles**. +5. In the Workspace Access dialog, select the **SecureWorkspace**. +6. Select the **workspace-admin** role, which makes this user the workspace administrator for the SecureWorkspace. + + When you are done adding roles, you are redirected back to the Invite Admin dialog. + + {:.important} + **Important:** Before you move on, make sure the **Enable RBAC Token** checkbox is checked. The RBAC token is what allows the new admin to send a token to the Admin API to configure the system programmatically. + +7. Click **Invite Admin** to send the invite. + + At this point in the getting started guide, you likely haven’t set up SMTP yet, so no email will be sent. Instead, you’ll later generate a registration link for the new administrator manually. + +#### Register the Admin + +1. Back on the **Teams** page, click **View** for the administrator you just created. +2. Click the **Generate registration link** button. + + Using this link, the new administrator can go to a web browser and paste it in to initiate his/her account and create an initial password. Again, normally, this would happen through SMTP, and the user would get this link through an email. + +3. Click the **copy icon** to copy the registration link, then save it. +4. Email or SMS the registration link to the new administrator — or use it yourself to test the login in the following steps. +5. Open a different browser or an incognito tab in the current browser so your existing login session is ignored. +6. Enter the registration link you copied previously into the new browser to log in with the new administrator (`secureworkspaceadmin`). + + If the registration link has expired, you can generate a new one by logging in with your `kong_admin` administrator and generating a new link. + +7. Enter a new password for your new administrator (save this in a secure place) and click on the **Register** button. + + If everything went well, you should see an “Account Setup Success” message. +{% endnavtab %} +{% navtab Using the Admin API %} + +{:.important} +> **Note** The following method refers to the `/users` endpoint and creates an Admin API user that won't be visible (or manageable) through Kong Manager. If you want to later administer the admin through Kong Manager, create it under the [`/admins`](/gateway/{{page.release}}/admin-api/admins/reference/) endpoint instead. + +Create a new user named `secureworkspaceadmin` with the RBAC token +`secureadmintoken`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/SecureWorkspace/rbac/users \ + -H Kong-Admin-Token: \ + --data 'name=secureworkspaceadmin' \ + --data 'user_token=secureadmintoken' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/SecureWorkspace/rbac/users \ + name=secureworkspaceadmin \ + user_token=secureadmintoken \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +Create a blank role in the workspace and name it `admin`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/SecureWorkspace/rbac/roles \ + -H Kong-Admin-Token: \ + --data 'name=admin' \ +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/SecureWorkspace/rbac/roles/ \ + name=admin \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +Give the `admin` role permissions to do everything on all endpoints in the +workspace: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/SecureWorkspace/rbac/roles/admin/endpoints/ \ + -H Kong-Admin-Token: \ + --data 'endpoint=*' + --data 'workspace=SecureWorkspace' \ + --data 'actions=*' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/SecureWorkspace/rbac/roles/admin/endpoints/ \ + endpoint='*' \ + workspace=SecureWorkspace \ + actions='*' \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +Grant the `admin` role to `secureworkspaceadmin`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/SecureWorkspace/rbac/users/secureworkspaceadmin/roles/ \ + -H Kong-Admin-Token: \ + --data 'role=admin' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/SecureWorkspace/rbac/users/secureworkspaceadmin/roles/ \ + roles=admin \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% endnavtabs %} + +## Verify the New Admin + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Click the **Login** button to be taken to a new screen to log in with your new administrator. +2. Enter the **Username** and **Password** of your new administrator and click **Login** again. + + Once you log in, you’ll notice that you can only see the SecureWorkspace. + +3. You can also verify that this user’s administration rights are limited. As this user, if you open the Teams tab and try to add new administrators, Admin API users (RBAC users), Groups, or Roles, you won’t have the permissions to do so. + +{% endnavtab %} +{% navtab Using the Admin API %} +1. Try to access the `default` workspace using `secureworkspaceadmin`'s user token. + + *Using cURL:* + ```sh + curl -H Kong-Admin-Token:secureadmintoken -X GET http://localhost:8001/default/rbac/users + ``` + *Or using HTTPie:* + + ```sh + http :8001/default/rbac/users Kong-Admin-Token:secureadmintoken + ``` + + You should get a `403 Forbidden` error message: + ``` + { + “message”: “secureworkspaceadmin, you do not have permissions to read this resource” + } + ``` +2. Then, try to access the same endpoint, but this time in the `SecureWorkspace`. + + *Using cURL:* + ```sh + curl -H Kong-Admin-Token:secureadmintoken -X GET http://localhost:8001/SecureWorkspace/rbac/users + ``` + *Or using HTTPie:* + + ```sh + http :8001/SecureWorkspace/rbac/users Kong-Admin-Token:secureadmintoken + ``` + This time, you should get a `200 OK` success message and a list of users. + +{% endnavtab %} +{% endnavtabs %} + +That's it! You are now controlling access to {{site.base_gateway}} administration with RBAC. + +## Reference: Using decK with RBAC and Workspaces + +### RBAC + +Once RBAC is enabled, you will have to pass the `kong-admin-token` in a header +any time you use decK: + +``` bash +deck sync --headers "kong-admin-token:mytoken" +``` +> **Note:** You should not use an RBAC token with Super Admin +privileges for decK. Always scope down to the exact permissions you need to +give decK. + +### Workspaces + +When you have multiple workspaces, decK creates a file for each one. Export +them as follows: + +``` bash +deck dump --all-workspaces +``` + +Or, to export the configuration for only one workspace: + +``` bash +deck dump --workspace SecureWorkspace +``` + +You can use these flags with any decK commands to update and export your +configuration. + +## Summary and next steps + +In this topic, you: + +* Enabled RBAC. +* Created a workspace named `SecureWorkspace`. +* Created an admin named `secureworkspaceadmin` and granted them permissions to manage to everything in the `SecureWorkspace`. + +Next, set up the [Dev Portal](/gateway/{{page.release}}/get-started/comprehensive/dev-portal/). diff --git a/app/gateway/2.6.x/get-started/comprehensive/prepare.md b/app/gateway/2.6.x/get-started/comprehensive/prepare.md new file mode 100644 index 000000000000..4fd897a0a21e --- /dev/null +++ b/app/gateway/2.6.x/get-started/comprehensive/prepare.md @@ -0,0 +1,156 @@ +--- +title: Prepare to Administer Kong Gateway +--- + +Before getting started with using {{site.base_gateway}}, verify that it was +installed correctly, and that you’re ready to administer it. + +## Before you begin + +Before you start this section, make sure that: + +* {{site.base_gateway}} is installed and running. +* Kong Manager (if applicable) and Kong Admin API ports are listening on the +appropriate port/IP/DNS settings. +* If using declarative configuration to configure {{site.base_gateway}}, +[decK](/deck/latest/installation) is installed. + +In this guide, an instance of {{site.base_gateway}} is referenced via +``. Make sure to replace `` with the hostname +of your control plane instance. + +## Verify the {{site.base_gateway}} configuration +{% navtabs %} +{% navtab Using Kong Manager %} +As a {{site.base_gateway}} user, you can use Kong Manager for environment +administration. You’re going to use it later on in this guide, so first make +sure you can access Kong Manager. + +Open a web browser and navigate to `http://localhost:8002`. + +If {{site.base_gateway}} was installed correctly, it automatically logs you +in and presents the Kong Manager Overview page. +{% endnavtab %} +{% navtab Using the Admin API %} +Ensure that you can send requests to the gateway's Admin API using either cURL +or HTTPie. + +View the current configuration by issuing the following command in a terminal +window: + + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X GET http://localhost:8001 +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http localhost:8001 +``` +{% endnavtab %} +{% endnavtabs %} + + +The current configuration returns. +{% endnavtab %} + +{% navtab Using decK (YAML) %} + +1. Check that decK is connected to {{site.base_gateway}}: + + ``` bash + deck ping + ``` + + You should see a success message with the version that you're + connected to: + ``` + Successfully connected to Kong! + Kong version: 2.1.0 + ``` + +2. Ensure that you can pull configuration from {{site.base_gateway}} by issuing +the following command in a terminal window: + + ``` bash + deck dump + ``` + + This command creates a `kong.yaml` file with the gateway's entire current + configuration, in the directory where decK is installed. + + You can also use this command at any time (for example, after a `deck sync`) + to see the {{site.base_gateway}}'s most recent configuration. + + {:.important} + > **Be careful!** Any subsequent `deck dump` will + overwrite the existing `kong.yaml` file. Create backups as needed. + +3. Open the file in your preferred code editor. Since you haven't configured +anything yet, the file should only contain the decK version: + + ``` yaml + _format_version: "1.1" + ``` + + You will use this file to configure {{site.base_gateway}}. + +{% endnavtab %} +{% endnavtabs %} + +## (Optional) Verify Control Plane and Data Plane connection + +If you're running {{site.base_gateway}} in Hybrid mode, you will need to +perform all tasks in this guide from the Control Plane. However, you can check +that all of your configurations are being pushed from the Control Plane to your +Data Planes using the Cluster Status CLI. + +Run the following on a Control Plane: + + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X GET http://localhost:8001/clustering/data-planes +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http :8001/clustering/data-planes +``` +{% endnavtab %} +{% endnavtabs %} + +The output shows all of the connected Data Plane instances in the cluster: + +```json +{ + "data": [ + { + "config_hash": "a9a166c59873245db8f1a747ba9a80a7", + "hostname": "data-plane-2", + "id": "ed58ac85-dba6-4946-999d-e8b5071607d4", + "ip": "192.168.10.3", + "last_seen": 1580623199, + "status": "connected" + }, + { + "config_hash": "a9a166c59873245db8f1a747ba9a80a7", + "hostname": "data-plane-1", + "id": "ed58ac85-dba6-4946-999d-e8b5071607d4", + "ip": "192.168.10.4", + "last_seen": 1580623200, + "status": "connected" + } + ], + "next": null +} +``` + +## Summary and next steps + +In this section, you learned about the methods of administering +{{site.base_gateway}} and how to access its configuration. Next, go on to +learn about [exposing your services with {{site.base_gateway}}](/gateway/{{page.release}}/get-started/comprehensive/expose-services/). diff --git a/app/gateway/2.6.x/get-started/comprehensive/protect-services.md b/app/gateway/2.6.x/get-started/comprehensive/protect-services.md new file mode 100644 index 000000000000..dd5a896c3be7 --- /dev/null +++ b/app/gateway/2.6.x/get-started/comprehensive/protect-services.md @@ -0,0 +1,184 @@ +--- +title: Protect your Services +--- +In this topic, you’ll learn how to enforce rate limiting using the Rate Limiting plugin. + +If you are following the getting started workflow, make sure you have completed [Exposing Your Services](/gateway/{{page.release}}/get-started/comprehensive/expose-services/) before moving on. + +## What is Rate Limiting? + +Kong's [Rate Limiting plugin](/hub/kong-inc/rate-limiting/) lets you restrict how many requests your upstream services receive from your API consumers, or how often each user can call the API. + +{:.note} +> The [**Rate Limiting Advanced**](/hub/kong-inc/rate-limiting-advanced/) plugin provides support for the sliding window algorithm to prevent the API from being overloaded near the window boundaries, and adds Redis support for greater performance. + +## Why Use Rate Limiting? + +Rate limiting protects the APIs from accidental or malicious overuse. Without rate limiting, each user may request as often as they like, which can lead to spikes of requests that starve other consumers. After rate limiting is enabled, API calls are limited to a fixed number of requests per second. + +## Set up Rate Limiting + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Access your Kong Manager instance and your **default** workspace. + +2. Go to **API Gateway** > **Plugins**. + +3. Click **New Plugin**. + +4. Scroll down to **Traffic Control** and find the **Rate Limiting Advanced** plugin. Click **Enable**. + +5. Apply the plugin as **Global**, which means the rate limiting applies to all requests, including every Service and Route in the Workspace. + + If you switched it to **Scoped**, the rate limiting would apply the plugin to only one Service, Route, or Consumer. + + > **Note**: By default, the plugin is automatically enabled when the form is submitted. You can also toggle the **This plugin is Enabled** button at the top of the form to configure the plugin without enabling it. For this example, keep the plugin enabled. + +6. Scroll down and complete only the following fields with the following parameters. + 1. config.limit: `5` + 2. config.sync_rate: `-1` + 3. config.window_size: `30` + + Besides the above fields, there may be others populated with default values. For this example, leave the rest of the fields as they are. + +7. Click **Create**. +{% endnavtab %} +{% navtab Using the Admin API %} + +{:.note} +> **Note:** This section sets up the basic Rate Limiting plugin. If you have a {{site.base_gateway}} instance, see instructions for **Using Kong Manager** to set up Rate Limiting Advanced with sliding window support instead. + +Call the Admin API on port `8001` and configure plugins to enable a limit of five (5) requests per minute, stored locally and in-memory, on the node. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/plugins \ + --data name=rate-limiting \ + --data config.minute=5 \ + --data config.policy=local +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f post :8001/plugins \ + name=rate-limiting \ + config.minute=5 \ + config.policy=local +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +{:.note} +> **Note:** This section sets up the basic Rate Limiting plugin. If you have a {{site.base_gateway}} instance, see instructions for **Using Kong Manager** to set up Rate Limiting Advanced with sliding window support instead. + +1. Add a new `plugins` section to the bottom of your `kong.yaml` file. Enable +`rate-limiting` with a limit of five (5) requests per minute, stored locally +and in-memory, on the node: + + ``` yaml + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + ``` + + This plugin will be applied globally, which means the rate limiting + applies to all requests, including every Service and Route in the Workspace. + + If you pasted the plugin section under an existing Service, Route, or + Consumer, the rate limiting would only apply to that specific + entity. + + >**Note**: By default, `enabled` is set to `true` for the plugin. You can + disable the plugin at any time by setting `enabled: false`. + +2. Sync the configuration: + + ``` bash + deck sync + ``` + +{% endnavtab %} +{% endnavtabs %} + + +## Validate Rate Limiting + +{% navtabs %} +{% navtab Using a Web Browser %} + +1. Enter `:8000/mock` and refresh your browser six times. + After the 6th request, you’ll receive an error message. +2. Wait at least 30 seconds and try again. + The service will be accessible until the sixth (6th) access attempt within a 30-second window. + +{% endnavtab %} +{% navtab Using the Admin API %} + +To validate rate limiting, access the API six (6) times from the CLI to confirm the requests are rate limited. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X GET http://localhost:8000/mock/anything +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock/anything +``` +{% endnavtab %} +{% endnavtabs %} + + + +After the 6th request, you should receive a 429 "API rate limit exceeded" error: +``` +{ +"message": "API rate limit exceeded" +} +``` +{% endnavtab %} +{% endnavtabs %} + + +## Summary and next steps + +In this section: + +* If using the Admin API or decK, you enabled the Rate Limiting plugin, +setting the rate limit to 5 times per minute. +* If using Kong Manager, you enabled the Rate Limiting Advanced plugin, +setting the rate limit to 5 times for every 30 seconds. + +Next, head on to learn about [proxy caching](/gateway/{{page.release}}/get-started/comprehensive/improve-performance/). diff --git a/app/gateway/2.6.x/get-started/comprehensive/secure-services.md b/app/gateway/2.6.x/get-started/comprehensive/secure-services.md new file mode 100644 index 000000000000..b9ed3ec1b564 --- /dev/null +++ b/app/gateway/2.6.x/get-started/comprehensive/secure-services.md @@ -0,0 +1,417 @@ +--- +title: Secure your Services Using Authentication +--- +In this topic, you’ll learn about API Gateway authentication, set up the Key Authentication plugin, and add a consumer. + +If you are following the getting started workflow, make sure you have completed [Improve Performance with Proxy Caching](/gateway/{{page.release}}/get-started/comprehensive/improve-performance/) before moving on. + +## What is Authentication? + +API gateway authentication is an important way to control the data that is allowed to be transmitted using your APIs. Basically, it checks that a particular consumer has permission to access the API, using a predefined set of credentials. + +{{site.base_gateway}} has a library of plugins that provide simple ways to implement the best known and most widely used [methods of API gateway authentication](/hub/#authentication). Here are some of the commonly used ones: + +* Basic Authentication +* Key Authentication +* OAuth 2.0 Authentication +* LDAP Authentication Advanced +* OpenID Connect + +Authentication plugins can be configured to apply to service entities within the {{site.base_gateway}}. In turn, service entities are mapped one-to-one with the upstream services they represent, essentially meaning that the authentication plugins apply directly to those upstream services. + +## Why use API Gateway Authentication? + +With authentication turned on, {{site.base_gateway}} won’t proxy requests unless the client successfully authenticates first. This means that the upstream (API) doesn’t need to authenticate client requests, and it doesn’t waste critical resources validating credentials. + +{{site.base_gateway}} has visibility into all authentication attempts, successful, failed, and so on, which provides the ability to catalog and dashboard those events to prove the right controls are in place, and to achieve compliance. Authentication also gives you an opportunity to determine how a failed request is handled. This might mean simply blocking the request and returning an error code, or in some circumstances, you might still want to provide limited access. + +In this example, you’re going to enable the **Key Authentication plugin**. API key authentication is one of the most popular ways to conduct API authentication and can be implemented to create and delete access keys as required. + +For more information, see [What is API Gateway Authentication?](https://konghq.com/learning-center/api-gateway/api-gateway-authentication). + +## Set up the Key Authentication Plugin + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Access your Kong Manager instance and your **default** workspace. +2. Go to the **Routes** page and select the **mocking** route you created. +3. Click **View**. +4. On the Scroll down and select the **Plugins** tab, then click **Add a Plugin**. +5. In the Authentication section, find the **Key Authentication** plugin and click **Enable**. +6. In the **Create new key-auth plugin** dialog, the plugin fields are automatically scoped to the route because the plugin is selected from the mocking Routes page. + + For this example, this means that you can use all of the default values. + +7. Click **Create**. + + Once the plugin is enabled on the route, **key-auth** displays under the Plugins section on the route’s overview page. + +Now, if you try to access the route without providing an API key, the request will fail, and you’ll see the message `"No API key found in request".` + +Before Kong proxies requests for this route, it needs an API key. For this example, since you installed the Key Authentication plugin, you need to create a consumer with an associated key first. +{% endnavtab %} +{% navtab Using the Admin API %} + +Call the Admin API on port `8001` and configure plugins to enable key +authentication. For this example, apply the plugin to the */mock* route you +created: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/routes/mocking/plugins \ + --data name=key-auth +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/routes/mocking/plugins \ + name=key-auth +``` +{% endnavtab %} +{% endnavtabs %} + + +Try to access the service again: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i http://localhost:8000/mock +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock +``` +{% endnavtab %} +{% endnavtabs %} + + +Since you added key authentication, you should be unable to access it: + +```sh +HTTP/1.1 401 Unauthorized +... +{ + "message": "No API key found in request" +} +``` + +Before Kong proxies requests for this route, it needs an API key. For this +example, since you installed the Key Authentication plugin, you need to create +a consumer with an associated key first. + +{% endnavtab %} +{% navtab Using decK (YAML) %} +1. Under the `mocking` route in the `routes` section of the `kong.yaml` file, +add a plugin section and enable the `key-auth` plugin: + + ``` yaml + plugins: + - name: key-auth + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: key-auth + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + +2. Sync the configuration: + + ``` bash + deck sync + ``` + +Now, if you try to access the route at `http://localhost:8000/mock` +without providing an API key, the request will fail, and you’ll see the message +`"No API key found in request".` + +Before Kong proxies requests for this route, it needs an API key. For this +example, since you installed the Key Authentication plugin, you need to create +a consumer with an associated key first. + +{% endnavtab %} +{% endnavtabs %} + + +## Set up Consumers and Credentials + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. In Kong Manager, go to **API Gateway** > **Consumers**. +2. Click **New Consumer**. +3. Enter the **Username** and **Custom ID**. For this example, use `consumer` for each field. +4. Click **Create**. +5. On the Consumers page, find your new consumer and click **View**. +6. Scroll down the page and click the **Credentials** tab. +7. Click **New Key Auth Credential**. +8. Set the key to `apikey` and click **Create**. + + The new Key Authentication ID displays on the **Consumers** page under the **Credentials** tab. +{% endnavtab %} +{% navtab Using the Admin API %} + +To create a consumer, call the Admin API and the consumer’s endpoint. +The following creates a new consumer called **consumer**: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers/ \ + --data username=consumer \ + --data custom_id=consumer +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/consumers \ + username=consumer \ + custom_id=consumer +``` +{% endnavtab %} +{% endnavtabs %} + + +Once provisioned, call the Admin API to provision a key for the consumer +created above. For this example, set the key to `apikey`. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers/consumer/key-auth \ + --data key=apikey +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/consumers/consumer/key-auth \ + key=apikey +``` +{% endnavtab %} +{% endnavtabs %} + + +If no key is entered, Kong automatically generates the key. + +Result: + +```sh +HTTP/1.1 201 Created +... +{ + "consumer": { + "id": "2c43c08b-ba6d-444a-8687-3394bb215350" + }, + "created_at": 1568255693, + "id": "86d283dd-27ee-473c-9a1d-a567c6a76d8e", + "key": "apikey" +} +``` + +You now have a consumer with an API key provisioned to access the route. + +{% endnavtab %} +{% navtab Using decK (YAML) %} +1. Add a `consumers` section to your `kong.yaml` file and create a new consumer: + + ``` yaml + consumers: + - custom_id: consumer + username: consumer + keyauth_credentials: + - key: apikey + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: key-auth + consumers: + - custom_id: consumer + username: consumer + keyauth_credentials: + - key: apikey + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + +2. Sync the configuration: + + ``` bash + deck sync + ``` + +You now have a consumer with an API key provisioned to access the route. + +{% endnavtab %} +{% endnavtabs %} + + +## Validate Key Authentication + +{% navtabs %} +{% navtab Using a Web Browser %} + +To validate the Key Authentication plugin, access your route through your browser by appending `?apikey=apikey` to the url: +``` +http://localhost:8000/mock?apikey=apikey +``` + +{% endnavtab %} +{% navtab Using the Admin API %} +To validate the Key Authentication plugin, access the *mocking* route again, using the header `apikey` with a key value of `apikey`. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i http://localhost:8000/mock/anything \ + -H 'apikey:apikey' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock/anything apikey:apikey +``` +{% endnavtab %} +{% endnavtabs %} + + +You should get an `HTTP/1.1 200 OK` message in response. + +{% endnavtab %} +{% endnavtabs %} + +## (Optional) Disable the plugin +If you are following this getting started guide topic by topic, you will need to use this API key in any requests going forward. If you don’t want to keep specifying the key, disable the plugin before moving on. + +{% navtabs %} +{% navtab Using Kong Manager %} +1. Go to the Plugins page and click on **View** for the key-auth row. +2. Use the toggle at the top of the page to switch the plugin from **Enabled** to **Disabled**. +{% endnavtab %} +{% navtab Using the Admin API %} + +Find the plugin ID and copy it: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X GET http://localhost:8001/routes/mocking/plugins/ +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/routes/mocking/plugins +``` +{% endnavtab %} +{% endnavtabs %} + + +Output: +```sh +"id": "2512e48d9-7by0-674c-84b7-00606792f96b" +``` + +Disable the plugin: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X PATCH http://localhost:8001/routes/mocking/plugins/{} \ + --data enabled=false +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f patch :8001/routes/mocking/plugins/{} \ + enabled=false +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +1. Disable the key-auth plugin in the `kong.yaml` file by setting +`enabled` to `false`: + + ``` yaml + plugins: + - name: key-auth + enabled: false + ``` + +2. Sync the configuration: + + ``` bash + $ deck sync + ``` + +{% endnavtab %} +{% endnavtabs %} + +## Summary and next steps + +In this topic, you: + +* Enabled the Key Authentication plugin. +* Created a new consumer named `consumer`. +* Gave the consumer an API key of `apikey` so that it could access the `/mock` route with authentication. + +Next, you’ll learn about [load balancing upstream services using targets](/gateway/{{page.release}}/get-started/comprehensive/load-balancing/). diff --git a/app/gateway/2.6.x/get-started/quickstart/adding-consumers.md b/app/gateway/2.6.x/get-started/quickstart/adding-consumers.md new file mode 100644 index 000000000000..6f0809b1c3f0 --- /dev/null +++ b/app/gateway/2.6.x/get-started/quickstart/adding-consumers.md @@ -0,0 +1,90 @@ +--- +title: Adding Consumers +--- + +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. + +## Before you start + +* You have installed and started {{site.base_gateway}}, either through the [Docker quickstart](/gateway/{{page.release}}/get-started/quickstart/) or a more [comprehensive installation](/gateway/{{page.release}}/install-and-run/). +* You have [configured a Service](/gateway/{{page.release}}/get-started/quickstart/configuring-a-service/) +* You have [enabled the key-auth plugin](/gateway/{{page.release}}/get-started/quickstart/enabling-plugins/) + +## 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](https://konghq.com/community/) +for help! + +[key-auth]: /hub/kong-inc/key-auth +[API-consumers]: /gateway/{{page.release}}/admin-api#create-consumer +[enabling-plugins]: /gateway/{{page.release}}/get-started/quickstart/enabling-plugins +[configuration]: /gateway/{{page.release}}/reference/configuration +[CLI]: /gateway/{{page.release}}/reference/cli +[proxy]: /gateway/{{page.release}}/reference/proxy +[API]: /gateway/{{page.release}}/admin-api +[cluster]: /gateway/{{page.release}}/reference/clustering diff --git a/app/gateway/2.6.x/get-started/quickstart/configuring-a-grpc-service.md b/app/gateway/2.6.x/get-started/quickstart/configuring-a-grpc-service.md new file mode 100644 index 000000000000..0e3f98ccfded --- /dev/null +++ b/app/gateway/2.6.x/get-started/quickstart/configuring-a-grpc-service.md @@ -0,0 +1,284 @@ +--- +title: Configuring a gRPC Service +--- + +Note: this guide assumes familiarity with gRPC; for learning how to set up +Kong with an upstream REST API, check out the [Configuring a Service guide][conf-service]. + +Starting with version 1.3, gRPC proxying is natively supported in Kong. In this +section, you'll learn how to configure Kong to manage your gRPC services. For the +purpose of this guide, we'll use [grpcurl][grpcurl] and [grpcbin][grpcbin] - they +provide a gRPC client and gRPC services, respectively. + +We will describe two setups: Single gRPC Service and Route and single gRPC Service +with multiple Routes. In the former, a single catch-all Route is configured, which +proxies all matching gRPC traffic to an upstream gRPC service; the latter demonstrates +how to use a Route per gRPC method. + +In Kong 1.3, gRPC support assumes gRPC over HTTP/2 framing. As such, make sure +you have at least one HTTP/2 proxy listener (check out the [Configuration Reference][configuration-reference] +for how to). In this guide, we will assume Kong is listening for HTTP/2 proxy +requests on port 9080. + +## Before you start + +You have installed and started {{site.base_gateway}}, either through the [Docker quickstart](/gateway/{{page.release}}/get-started/quickstart/) or a more [comprehensive installation](/gateway/{{page.release}}/install-and-run/). + +## 1. Single gRPC Service and Route + +Issue the following request to create a gRPC Service (assuming your gRPC +server is listening in localhost, port 15002): + +```bash +curl -XPOST localhost:8001/services \ + --data name=grpc \ + --data protocol=grpc \ + --data host=localhost \ + --data port=15002 +``` + +Issue the following request to create a gRPC route: + +```bash +curl -XPOST localhost:8001/services/grpc/routes \ + --data protocols=grpc \ + --data name=catch-all \ + --data paths=/ +``` + +Using the [grpcurl][grpcurl] command line client, issue the following gRPC +request: + +```bash +grpcurl -v -d '{"greeting": "Kong 1.3!"}' \ + -plaintext localhost:9080 hello.HelloService.SayHello +``` + +The response should resemble the following: + +``` +Resolved method descriptor: +rpc SayHello ( .hello.HelloRequest ) returns ( .hello.HelloResponse ); + +Request metadata to send: +(empty) + +Response headers received: +content-type: application/grpc +date: Tue, 16 Jul 2019 21:37:36 GMT +server: openresty/1.15.8.1 +via: kong/1.2.1 +x-kong-proxy-latency: 0 +x-kong-upstream-latency: 0 + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response trailers received: +(empty) +Sent 1 request and received 1 response +``` + +Notice that Kong response headers, such as `via` and `x-kong-proxy-latency`, were +inserted in the response. + +## 2. Single gRPC Service with Multiple Routes + +Building on top of the previous example, let's create a few more routes, for +individual gRPC methods. + +The gRPC "HelloService" service being used in this example exposes a few different +methods, as can be seen in [its protobuf file][protobuf]. We will create individual +routes for its "SayHello" and LotsOfReplies methods. + +Create a Route for "SayHello": + +```bash +curl -X POST localhost:8001/services/grpc/routes \ + --data protocols=grpc \ + --data paths=/hello.HelloService/SayHello \ + --data name=say-hello +``` + +Create a Route for "LotsOfReplies": + +```bash +curl -X POST localhost:8001/services/grpc/routes \ + --data protocols=grpc \ + --data paths=/hello.HelloService/LotsOfReplies \ + --data name=lots-of-replies +``` + +With this setup, gRPC requests to the "SayHello" method will match the first +Route, while requests to "LotsOfReplies" will be routed to the latter. + +Issue a gRPC request to the "SayHello" method: + +```bash +grpcurl -v -d '{"greeting": "Kong 1.3!"}' \ + -H 'kong-debug: 1' -plaintext \ + localhost:9080 hello.HelloService.SayHello +``` + +(Notice we are sending a header `kong-debug`, which causes Kong to insert +debugging information in response headers.) + +The response should look like: + +``` +Resolved method descriptor: +rpc SayHello ( .hello.HelloRequest ) returns ( .hello.HelloResponse ); + +Request metadata to send: +kong-debug: 1 + +Response headers received: +content-type: application/grpc +date: Tue, 16 Jul 2019 21:57:00 GMT +kong-route-id: 390ef3d1-d092-4401-99ca-0b4e42453d97 +kong-service-id: d82736b7-a4fd-4530-b575-c68d94c3493a +kong-service-name: s1 +server: openresty/1.15.8.1 +via: kong/1.2.1 +x-kong-proxy-latency: 0 +x-kong-upstream-latency: 0 + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response trailers received: +(empty) +Sent 1 request and received 1 response +``` + +Notice the Route ID should refer to the first route we created. + +Similarly, let's issue a request to the "LotsOfReplies" gRPC method: + +```bash +grpcurl -v -d '{"greeting": "Kong 1.3!"}' \ + -H 'kong-debug: 1' -plaintext \ + localhost:9080 hello.HelloService.LotsOfReplies +``` + +The response should look like the following: + +``` +Resolved method descriptor: +rpc LotsOfReplies ( .hello.HelloRequest ) returns ( stream .hello.HelloResponse ); + +Request metadata to send: +kong-debug: 1 + +Response headers received: +content-type: application/grpc +date: Tue, 30 Jul 2019 22:21:40 GMT +kong-route-id: 133659bb-7e88-4ac5-b177-bc04b3974c87 +kong-service-id: 31a87674-f984-4f75-8abc-85da478e204f +kong-service-name: grpc +server: openresty/1.15.8.1 +via: kong/1.2.1 +x-kong-proxy-latency: 14 +x-kong-upstream-latency: 0 + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response trailers received: +(empty) +Sent 1 request and received 10 responses +``` + +Notice that the `kong-route-id` response header now carries a different value +and refers to the second Route created in this page. + +**Note:** +Some gRPC clients (typically CLI clients) issue ["gRPC Reflection Requests"][grpc-reflection] +as a means of determining what methods a server exports and how those methods are called. +Said requests have a particular path; for example, `/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo` +is a valid reflection path. As with any proxy request, Kong needs to know how to +route these; in the current example, they would be routed to the catch-all route +(whose path is `/`, matching any path). If no route matches the gRPC reflection +request, Kong will respond, as expected, with a `404 Not Found` response. + +## 3. Enabling Plugins + +Kong 1.3 gRPC support is compatible with Logging and Observability plugins; for +example, let's try out the [File Log][file-log] plugin with gRPC. + +Issue the following request to enable File Log on the "SayHello" route: + +```bash +curl -X POST localhost:8001/routes/say-hello/plugins \ + --data name=file-log \ + --data config.path=grpc-say-hello.log +``` + +Follow the output of the log as gRPC requests are made to "SayHello": + +``` +tail -f grpc-say-hello.log +{"latencies":{"request":8,"kong":5,"proxy":3},"service":{"host":"localhost","created_at":1564527408,"connect_timeout":60000,"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","protocol":"grpc","name":"grpc","read_timeout":60000,"port":15002,"updated_at":1564527408,"write_timeout":60000,"retries":5},"request":{"querystring":{},"size":"46","uri":"\/hello.HelloService\/SayHello","url":"http:\/\/localhost:9080\/hello.HelloService\/SayHello","headers":{"host":"localhost:9080","content-type":"application\/grpc","kong-debug":"1","user-agent":"grpc-go\/1.20.0-dev","te":"trailers"},"method":"POST"},"client_ip":"127.0.0.1","tries":[{"balancer_latency":0,"port":15002,"balancer_start":1564527732522,"ip":"127.0.0.1"}],"response":{"headers":{"kong-route-id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","content-type":"application\/grpc","connection":"close","kong-service-name":"grpc","kong-service-id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","kong-route-name":"say-hello","via":"kong\/1.2.1","x-kong-proxy-latency":"5","x-kong-upstream-latency":"3"},"status":200,"size":"298"},"route":{"id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","updated_at":1564527431,"protocols":["grpc"],"created_at":1564527431,"service":{"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c"},"name":"say-hello","preserve_host":false,"regex_priority":0,"strip_path":false,"paths":["\/hello.HelloService\/SayHello"],"https_redirect_status_code":426},"started_at":1564527732516} +{"latencies":{"request":3,"kong":1,"proxy":1},"service":{"host":"localhost","created_at":1564527408,"connect_timeout":60000,"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","protocol":"grpc","name":"grpc","read_timeout":60000,"port":15002,"updated_at":1564527408,"write_timeout":60000,"retries":5},"request":{"querystring":{},"size":"46","uri":"\/hello.HelloService\/SayHello","url":"http:\/\/localhost:9080\/hello.HelloService\/SayHello","headers":{"host":"localhost:9080","content-type":"application\/grpc","kong-debug":"1","user-agent":"grpc-go\/1.20.0-dev","te":"trailers"},"method":"POST"},"client_ip":"127.0.0.1","tries":[{"balancer_latency":0,"port":15002,"balancer_start":1564527733555,"ip":"127.0.0.1"}],"response":{"headers":{"kong-route-id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","content-type":"application\/grpc","connection":"close","kong-service-name":"grpc","kong-service-id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","kong-route-name":"say-hello","via":"kong\/1.2.1","x-kong-proxy-latency":"1","x-kong-upstream-latency":"1"},"status":200,"size":"298"},"route":{"id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","updated_at":1564527431,"protocols":["grpc"],"created_at":1564527431,"service":{"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c"},"name":"say-hello","preserve_host":false,"regex_priority":0,"strip_path":false,"paths":["\/hello.HelloService\/SayHello"],"https_redirect_status_code":426},"started_at":1564527733554} +``` + +[enabling-plugins]: /gateway/{{page.release}}/get-started/quickstart/enabling-plugins +[conf-service]: /gateway/{{page.release}}/get-started/quickstart/configuring-a-service +[configuration-reference]: /gateway/{{page.release}}/reference/configuration/ +[grpc-reflection]: https://github.com/grpc/grpc/blob/master/doc/server_reflection_tutorial.md +[grpcbin]: https://github.com/moul/grpcbin +[grpcurl]: https://github.com/fullstorydev/grpcurl +[protobuf]: https://raw.githubusercontent.com/moul/pb/master/hello/hello.proto +[file-log]: /hub/kong-inc/file-log +[zipkin]: /hub/kong-inc/zipkin diff --git a/app/gateway/2.6.x/get-started/quickstart/configuring-a-service.md b/app/gateway/2.6.x/get-started/quickstart/configuring-a-service.md new file mode 100644 index 000000000000..a77e174f5225 --- /dev/null +++ b/app/gateway/2.6.x/get-started/quickstart/configuring-a-service.md @@ -0,0 +1,132 @@ +--- +title: Configuring a Service +--- + +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 [httpbin API][httpbin]. Httpbin 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. + +## Before you start +You have installed and started {{site.base_gateway}}, either through the [Docker quickstart](/gateway/{{page.release}}/get-started/quickstart/) or a more [comprehensive installation](/gateway/{{page.release}}/install-and-run/). + +## 1. Add your Service using the Admin API + +Issue the following cURL request to add your first Service (pointing to the [httpbin API][httpbin]) +to Kong: + +```bash +curl -i -X POST \ + --url http://localhost:8001/services/ \ + --data 'name=example-service' \ + --data 'url=https://httpbin.konghq.com' +``` + +You should receive a response similar to: + +```http +HTTP/1.1 201 Created +Content-Type: application/json +Connection: keep-alive + +{ + "host":"httpbin.konghq.com", + "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]: /gateway/{{page.release}}/admin-api +[enabling-plugins]: /gateway/{{page.release}}/get-started/quickstart/enabling-plugins +[proxy-port]: /gateway/{{page.release}}/reference/configuration/#nginx-section +[httpbin]: https://httpbin.konghq.com/ diff --git a/app/gateway/2.6.x/get-started/quickstart/enabling-plugins.md b/app/gateway/2.6.x/get-started/quickstart/enabling-plugins.md new file mode 100644 index 000000000000..dfe5ced0ed91 --- /dev/null +++ b/app/gateway/2.6.x/get-started/quickstart/enabling-plugins.md @@ -0,0 +1,69 @@ +--- +title: Enabling Plugins +--- + +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. + +## Before you start + +* You have installed and started {{site.base_gateway}}, either through the [Docker quickstart](/gateway/{{page.release}}/get-started/quickstart/) or a more [comprehensive installation](/gateway/{{page.release}}/install-and-run/) +* You have [configured your Service](/gateway/{{page.release}}/get-started/quickstart/configuring-a-service/) in {{site.base_gateway}} + +## 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 API key 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]: /hub/kong-inc/key-auth +[plugins]: /hub/ +[adding-consumers]: /gateway/{{page.release}}/get-started/quickstart/adding-consumers diff --git a/app/gateway/2.6.x/get-started/quickstart/index.md b/app/gateway/2.6.x/get-started/quickstart/index.md new file mode 100644 index 000000000000..cefc4d8ff424 --- /dev/null +++ b/app/gateway/2.6.x/get-started/quickstart/index.md @@ -0,0 +1,117 @@ +--- +title: Start Kong Gateway +--- + +In this section, you'll learn how to install and manage your {{site.base_gateway}} instance. First, you'll start {{site.base_gateway}} to gain access to its Admin +API, where you'll manage entities including Services, Routes, and Consumers. + +## Start {{site.base_gateway}} using Docker with a database + +One quick way to get {{site.base_gateway}} up and running is by using [Docker with a PostgreSQL database](/gateway/{{page.release}}/install-and-run/docker/). We recommend this method to test out basic {{site.base_gateway}} functionality. + +For a comprehensive list of installation options, see our [Install page](/gateway/{{page.release}}/install-and-run/). + +1. Create a Docker network: + + ```bash + docker network create kong-net + ``` + +2. Run a PostGreSQL container: + + ```bash + docker run -d --name kong-database \ + --network=kong-net \ + -p 5432:5432 \ + -e "POSTGRES_USER=kong" \ + -e "POSTGRES_DB=kong" \ + -e "POSTGRES_PASSWORD=kong" \ + postgres:9.6 + ``` + + Data sent through the Admin API is stored in Kong's [datastore][datastore-section] (Kong + supports PostgreSQL and Cassandra). + +3. Prep your database: + + ```bash + docker run --rm \ + --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_USER=kong" \ + -e "KONG_PG_PASSWORD=kong" \ + -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ + kong:latest kong migrations bootstrap + ``` + +4. Start Kong: + + ```bash + docker run -d --name kong \ + --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_USER=kong" \ + -e "KONG_PG_PASSWORD=kong" \ + -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 127.0.0.1:8001:8001 \ + -p 127.0.0.1:8444:8444 \ + kong:latest + ``` + +5. Navigate to `http://localhost:8001/`. + +## Kong default ports + +By default, Kong listens on the following ports: + +- `8000`: listens for incoming `HTTP` traffic from your + clients, and forwards it to your upstream services. +- `8001`: [Admin API][API] listens for calls from the command line over `HTTP`. +- `8443`: listens for incoming HTTPS traffic. This port has a + similar behavior to `8000`, except that it expects `HTTPS` + traffic only. This port can be disabled via the configuration file. +- `8444`: [Admin API][API] listens for `HTTPS` traffic. + +## Lifecycle commands + +{:.note} +> **Note**: If you are using Docker, [`exec`](https://docs.docker.com/engine/reference/commandline/exec) into the Docker container to use these commands. + +Stop {{site.base_gateway}} using the [stop][CLI] command: + +```bash +kong stop +``` + +Reload {{site.base_gateway}} using the [reload][CLI] command: + +```bash +kong reload +``` + +Start {{site.base_gateway}} using the [start][CLI] command: + +```bash +kong start +``` + +## Next Steps + +Now that you have {{site.base_gateway}} running, you can interact with the Admin API. + +To begin, go to [Configuring a Service ›][configuring-a-service] + +[configuration-loading]: /gateway/{{page.release}}/reference/configuration/#configuration-loading +[CLI]: /gateway/{{page.release}}/reference/cli +[API]: /gateway/{{page.release}}/admin-api +[datastore-section]: /gateway/{{page.release}}/reference/configuration/#datastore-section +[configuring-a-service]: /gateway/{{page.release}}/get-started/quickstart/configuring-a-service diff --git a/app/gateway/2.6.x/index.md b/app/gateway/2.6.x/index.md new file mode 100644 index 000000000000..127f685f10ec --- /dev/null +++ b/app/gateway/2.6.x/index.md @@ -0,0 +1,170 @@ +--- +title: Kong Gateway +subtitle: API gateway built for hybrid and multi-cloud, optimized for microservices and distributed architectures +--- + +{{site.base_gateway}} is a lightweight, fast, and flexible cloud-native API +gateway. An API gateway is a reverse proxy that lets you manage, configure, and route +requests to your APIs. + +{{site.base_gateway}} runs in front of any RESTful API and can be extended through +modules and plugins. It's designed to run on decentralized architectures, including +hybrid-cloud and multi-cloud deployments. + +With {{site.base_gateway}}, users can: + +* Leverage workflow automation and modern GitOps practices +* Decentralize applications/services and transition to microservices +* Create a thriving API developer ecosystem +* Proactively identify API-related anomalies and threats +* Secure and govern APIs/services, and improve API visibility across the +entire organization + +## Extending the {{site.base_gateway}} + +{{site.base_gateway}} is a Lua application running in Nginx. {{site.base_gateway}} +is distributed along with [OpenResty](https://openresty.org/), which is a bundle +of modules that extend the [lua-nginx-module](https://github.com/openresty/lua-nginx-module). + +This sets the foundations for a modular architecture, where +plugins can be enabled and executed at runtime. At its core, +{{site.base_gateway}} implements database abstraction, routing, and plugin +management. Plugins can live in separate code bases and be injected anywhere +into the request lifecycle, all with a few lines of code. + +Kong provides many [plugins](#kong-gateway-plugins) for you to use in your +Gateway deployments. You can also create your own custom plugins. For more +information, see the +[plugin development guide](/gateway/{{page.release}}/plugin-development), +the [PDK reference](/gateway/{{page.release}}/pdk/), and the guide on +[creating plugins with other languages](/gateway/{{page.release}}/reference/external-plugins). + +## Packages and modes + +{{site.base_gateway}} is available in the following modes: + +**{{site.base_gateway}} (OSS)**: an open-source package containing the basic API gateway +functionality and open-source plugins. You can manage the open-source Gateway +with Kong's [Admin API](#kong-admin-api) or with [declarative configuration](#deck). + +**{{site.base_gateway}}** (available in +[Free, Plus, or Enterprise modes](https://konghq.com/pricing)): Kong's API gateway +with added functionality. +* In **Free mode** , + this package adds [Kong Manager](#kong-manager) to the basic open-source functionality. +* In **Plus mode** , you have access to more +{{site.base_gateway}} features, but only through {{site.konnect_saas}}. +See the [{{site.konnect_saas}} documentation](/konnect/) and the +**Plus**-labelled plugins on the [Plugin Hub](/hub/) for more information. +* With an **Enterprise** subscription , + it also includes: + * [Dev Portal](#kong-dev-portal) + * [Vitals](#kong-vitals) + * [RBAC](/gateway/{{page.release}}/admin-api/rbac/reference/) + * [Enterprise plugins](/hub/) + +You can manage {{site.base_gateway}} in Free or Enterprise mode with Kong's +[Admin API](#kong-admin-api), [declarative configuration](#deck), or [Kong Manager](#kong-manager). + +This package is also available as part of +[{{site.konnect_product_name}}](/konnect/). + +![Introduction to {{site.base_gateway}}](/assets/images/products/gateway/gateway_overview.png) +> _Figure 1: Diagram of {{site.base_gateway}} modules and how they relate to the +foundational Gateway components._ +>
    +> _Requests flow from an API client into the +Gateway, are modified and managed by the proxy based on your Gateway +configuration, and forwarded to upstream services._ + +## Features + +### Kong Admin API + +[Kong Admin API](/gateway/{{page.release}}/admin-api) provides a RESTful +interface for administration and configuration of Services, Routes, Plugins, and +Consumers. All of the tasks you can perform against the Gateway can be automated +using the Kong Admin API. + +### Kong Manager +{:.badge .free} + +[Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager) is +the graphical user interface (GUI) for {{site.base_gateway}}. It uses the Kong +Admin API under the hood to administer and control {{site.base_gateway}}. + +Here are some of the things you can do with Kong Manager: + +* Create new Routes and Services +* Activate or deactivate plugins with a couple of clicks +* Group your teams, services, plugins, consumer management, and everything else +exactly how you want them +* Monitor performance: visualize cluster-wide, workspace-level, or +object-level health using intuitive, customizable dashboards + +### Kong Dev Portal +{:.badge .enterprise} + +[Kong Dev Portal](/gateway/{{page.release}}/developer-portal) is used to onboard new developers and to generate API documentation, create custom pages, manage API versions, and secure developer access. + +### Kong Vitals +{:.badge .enterprise} + +[Kong Vitals](/gateway/{{page.release}}/vitals) provides useful metrics about the health and performance of your {{site.base_gateway}} nodes, as well as metrics about the usage of your proxied APIs. You can visually monitor vital signs and pinpoint anomalies in real-time, and use visual API analytics to see exactly how your APIs and Gateway are performing and access key statistics. Kong Vitals is part of the Kong Manager UI. + +### Kubernetes + +{{site.base_gateway}} can run natively on Kubernetes with its custom [ingress controller](/kubernetes-ingress-controller/), Helm chart, and Operator. A Kubernetes ingress controller is a proxy that exposes Kubernetes services from applications (for example, Deployments, ReplicaSets) running on a Kubernetes cluster to client applications running outside of the cluster. The intent of an ingress controller is to provide a single point of control for all incoming traffic into the Kubernetes cluster. + +### {{site.base_gateway}} plugins + +[{{site.base_gateway}} plugins](/hub/) provide advanced functionality to better manage your API and microservices. With turnkey capabilities to meet the most challenging use cases, {{site.base_gateway}} plugins ensure maximum control and minimizes unnecessary overhead. Enable features like authentication, rate-limiting, and transformations by enabling {{site.base_gateway}} plugins through Kong Manager or the Admin API. + +## Tools +Kong also provides API lifecycle management tools that you can use with {{site.base_gateway}}. + +### Insomnia + +[Insomnia](https://docs.insomnia.rest) enables spec-first development for all REST and GraphQL services. With Insomnia, organizations can accelerate design and test workflows using automated testing, direct Git sync, and inspection of all response types. Teams of all sizes can use Insomnia to increase development velocity, reduce deployment risk, and increase collaboration. + +### decK +[decK](/deck) helps manage {{site.base_gateway}}’s configuration in a declarative fashion. +This means that a developer can define the desired state of {{site.base_gateway}} or +{{site.konnect_short_name}} – services, routes, plugins, and more – and let decK handle +implementation without needing to execute each step manually, as you would with +the Kong Admin API. + + +## Get started with {{site.base_gateway}} + +[Download and install {{site.base_gateway}}](/gateway/{{page.release}}/install-and-run). +To test it out, you can choose either the open-source package, or +run {{site.base_gateway}} in free mode and also try out Kong Manager. + +After installation, get started with one of our introductory guides: +* **[Quickstart](/gateway/{{page.release}}/get-started/quickstart/)**: An introduction to +{{site.base_gateway}}, common objects, and basic Admin API commands. +* **[Getting started guide](/gateway/{{page.release}}/get-started/comprehensive/)**: +The complete {{site.base_gateway}} +getting started guide provides in-depth examples, explanations, and step-by-step +instructions, and explores Kong's many available tools for managing the gateway. + +### Try in {{site.konnect_short_name}} + +[{{site.konnect_product_name}}](/konnect/) can manage {{site.base_gateway}} +instances. With this setup, Kong hosts the control plane and you host your +own data planes. + +There are a few ways to test out the Gateway's Plus or Enterprise features: + +* Sign up for a [free trial of {{site.konnect_product_name}} Plus](https://cloud.konghq.com/register). +* Check out learning labs at [Kong Academy]({{site.links.learn}}). +* If you are interested in evaluating Enterprise features locally, +[request a demo](https://konghq.com/get-started/#request-demo) and a Kong +representative will reach out with details to get you started. + +## Support policy +Kong follows a structured approach to versioning its products. + +For the latest version support information for {{site.ee_product_name}} and +{{site.mesh_product_name}}, see our [version support policy](/gateway/latest/support-policy/). diff --git a/app/gateway/2.6.x/install-and-run/amazon-linux.md b/app/gateway/2.6.x/install-and-run/amazon-linux.md new file mode 100644 index 000000000000..dffeb5b911e9 --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/amazon-linux.md @@ -0,0 +1,98 @@ +--- +title: Install Kong Gateway on Amazon Linux +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +Kong is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A [supported system](/gateway/{{page.release}}/compatibility/) with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* (Enterprise only) A `license.json` file from Kong. + +## Download and Install + +You can install {{site.base_gateway}} by downloading an installation package or using our yum repository. + +{:.note} +> **Note:** {{site.base_gateway}} supports running on [AWS Graviton processors](https://aws.amazon.com/ec2/graviton/). It can run in all AWS Regions where AWS Graviton is supported. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on Amazon Linux from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/amzn/%{amzn}/noarch/kong-enterprise-edition-{{page.versions.ee}}.aws.noarch.rpm) +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/amzn/%{amzn}/x86_64/kong-{{page.versions.ce}}.aws.x86_64.rpm) +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package: + +{% capture install_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}}.rpm +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}}.rpm +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + +{% endnavtab %} +{% navtab YUM repository %} + +Install the YUM repository from the command line. + +1. Download the Kong YUM repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.rpm.txt?distro=amzn&codename=$(rpm --eval '%{amzn}')" | sudo tee /etc/yum.repos.d/kong-gateway-legacy.repo > /dev/null + sudo yum -q makecache -y --disablerepo='*' --enablerepo='kong-gateway-legacy' + ``` + +2. Install Kong: + +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}} +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}} +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.6.x/install-and-run/centos.md b/app/gateway/2.6.x/install-and-run/centos.md new file mode 100644 index 000000000000..ec8e4e538d5f --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/centos.md @@ -0,0 +1,94 @@ +--- +title: Install Kong Gateway on CentOS +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +Kong is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A [supported system](/gateway/{{page.release}}/compatibility/) with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* (Enterprise only) A `license.json` file from Kong + +## Download and Install + +You can install {{site.base_gateway}} by downloading an installation package or using our yum repository. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on CentOS from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/el/%{centos_ver}/x86_64/kong-enterprise-edition-{{page.versions.ee}}.el%{centos_ver}.noarch.rpm) +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/el/%{centos_ver}/x86_64/kong-{{page.versions.ce}}.el%{centos_ver}.x86_64.rpm) + ``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package using `yum`. + +{% capture install_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}}.rpm +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}}.rpm +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + +{% endnavtab %} +{% navtab YUM repository %} + +Install the YUM repository from the command line. + +1. Download the Kong YUM repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.rpm.txt?distro=el&codename=$(rpm --eval '%{rhel}')" | sudo tee /etc/yum.repos.d/kong-gateway-legacy.repo + sudo yum -q makecache -y --disablerepo='*' --enablerepo='kong-gateway-legacy' + ``` + +2. Install Kong: +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}} +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}} +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.6.x/install-and-run/debian.md b/app/gateway/2.6.x/install-and-run/debian.md new file mode 100644 index 000000000000..31691acb156a --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/debian.md @@ -0,0 +1,115 @@ +--- +title: Install Kong Gateway on Debian +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A [supported system](/gateway/{{page.release}}/compatibility/) with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* The following tools are installed: + * [`curl`](https://curl.se/) + * [`lsb-release`](https://packages.debian.org/lsb-release) + * [`apt-transport-https`](https://packages.debian.org/apt-transport-https) (Only if installing the APT repository) +* (Enterprise only) A `license.json` file from Kong. + +## Download and install + +You can install {{site.base_gateway}} by downloading an installation package or using our APT repository. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on Debian from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.all.deb "{{ site.links.direct }}/gateway-legacy/deb/debian/pool/stretch/main/k/ko/kong-enterprise-edition_{{page.versions.ee}}/kong-enterprise-edition_{{page.versions.ee}}_all.deb" +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.amd64.deb "{{ site.links.direct }}/gateway-legacy/deb/debian/pool/stretch/main/k/ko/kong_{{page.versions.ce}}/kong_{{page.versions.ce}}_amd64.deb" +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package: + +{% capture install_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo apt install -y ./kong-enterprise-edition-{{page.versions.ee}}.all.deb +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo apt install -y ./kong-{{page.versions.ce}}.amd64.deb +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + +{% navtabs_ee %} +{% navtab Kong Gateway %} +{:.note .no-icon} +> Once {{ site.base_gateway }} is installed, you may want to run `sudo apt-mark hold kong-enterprise-edition`. This will prevent an accidental upgrade to a new version. +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +{:.note .no-icon} +> Once {{ site.base_gateway }} is installed, you may want to run `sudo apt-mark hold kong`. This will prevent an accidental upgrade to a new version. +{% endnavtab %} +{% endnavtabs_ee %} + +{% endnavtab %} +{% navtab APT repository %} + +Install the APT repository from the command line. + +{% assign gpg_key = site.data.installation.gateway.legacy.gpg_key %} + +1. Download the Kong APT repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/gpg.{{ gpg_key }}.key" | gpg --dearmor | sudo tee -a /usr/share/keyrings/kong-gateway-legacy-archive-keyring.gpg > /dev/null + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.deb.txt?distro=debian&codename=stretch" | sudo tee /etc/apt/sources.list.d/kong-gateway-legacy.list > /dev/null + ``` +2. Update the repository: + ```bash + sudo apt-get update + ``` +3. Install Kong: + +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo apt install -y kong-enterprise-edition={{page.versions.ee}} +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo apt install -y kong={{page.versions.ce}} +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.6.x/install-and-run/docker.md b/app/gateway/2.6.x/install-and-run/docker.md new file mode 100644 index 000000000000..55c6943667e6 --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/docker.md @@ -0,0 +1,416 @@ +--- +title: Install Kong Gateway on Docker +--- + + + + +{:.install-banner} +> See the list of Docker tags and pull the Docker image: +> * [**{{site.base_gateway}}**](https://hub.docker.com/r/kong/kong-gateway/tags){:.install-listing-link} +> * [**{{site.base_gateway}} (OSS)**](https://hub.docker.com/_/kong){:.install-listing-link} +> +> (latest {{site.base_gateway}} version: {{page.releases_hash[page.version-index].ee-version}}) + +{{site.base_gateway}} supports both PostgreSQL 9.5+ and Cassandra 3.11.* as its +datastore. This guide provides steps to configure PostgreSQL. + +If you prefer to use the open-source {{site.base_gateway}} image with Docker +Compose, Kong also provides a +[Docker Compose template](https://github.com/Kong/docker-kong/tree/master/compose) +with built-in orchestration and scalability. + +Some [older {{site.base_gateway}} images](https://support.konghq.com/support/s/article/Downloading-older-Kong-versions) +are not publicly accessible. If you need a specific patch version and can't +find it on [Kong's public Docker Hub page](https://hub.docker.com/r/kong/kong-gateway), contact +[Kong Support](https://support.konghq.com/). + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A Docker-enabled system with proper Docker access +* (Enterprise only) A `license.json` file from Kong + +Choose a path to install {{site.base_gateway}}: +* [With a database](#install-kong-gateway-with-a-database): Use a database to +store Kong entity configurations. Can use the Admin API or declarative +configuration files to configure Kong. +* [Without a database (DB-less mode)](#install-kong-gateway-in-db-less-mode): +Store Kong configuration in-memory on the node. In this mode, the Admin API is +read only, and you have to manage Kong using declarative configuration. + +If this is your first time trying out {{site.base_gateway}}, we recommend installing it +with a database. + +## Install {{site.base_gateway}} with a database + +Set up a {{site.base_gateway}} container with a PostgreSQL database to store +Kong configuration. + +### Prepare the database + +1. Create a custom Docker network to allow the containers to discover and +communicate with each other: + + ```sh + docker network create kong-net + ``` + + You can name this network anything you want. We use `kong-net` as + an example throughout this guide. + +1. Start a PostgreSQL container: + + ```sh + docker run -d --name kong-database \ + --network=kong-net \ + -p 5432:5432 \ + -e "POSTGRES_USER=kong" \ + -e "POSTGRES_DB=kong" \ + -e "POSTGRES_PASSWORD=kongpass" \ + postgres:9.6 + ``` + + * `POSTGRES_USER` and `POSTGRES_DB`: Set these values to `kong`. This is + the default value that {{site.base_gateway}} expects. + * `POSTGRES_PASSWORD`: Set the database password to any string. + + In this example, the PostgreSQL container named `kong-database` can + communicate with any containers on the `kong-net` network. + +1. Prepare the Kong database: + +{% capture migrations %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```sh +docker run --rm --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_PASSWORD=kongpass" \ + -e "KONG_PASSWORD=test" \ +kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine kong migrations bootstrap +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```sh +docker run --rm --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_PASSWORD=kongpass" \ +kong:{{page.releases_hash[page.version-index].ce-version}}-alpine kong migrations bootstrap +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ migrations | indent | replace: " ", "" }} + + Where: + * [`KONG_DATABASE`](/gateway/{{page.release}}/reference/configuration/#database): + Specifies the type of database that Kong is using. + * [`KONG_PG_HOST`](/gateway/{{page.release}}/reference/configuration/#postgres-settings): + The name of the PostgreSQL Docker container that is communicating over the + `kong-net` network, from the previous step. + * [`KONG_PG_PASSWORD`](/gateway/{{page.release}}/reference/configuration/#postgres-settings): + The password that you set when bringing up the PostgreSQL container in the + previous step. + * `KONG_PASSWORD` (Enterprise only): The default password for the admin + super user for {{site.base_gateway}}. + * `{IMAGE-NAME:TAG} kong migrations bootstrap`: + In order, this is the {{site.base_gateway}} container name and tag, followed by the + command to Kong to prepare the PostgreSQL database. + +### Start {{site.base_gateway}} + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + +1. Run the following command to start a container with {{site.base_gateway}}: +{% capture start_container %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```sh +docker run -d --name kong-gateway \ + --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_USER=kong" \ + -e "KONG_PG_PASSWORD=kongpass" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \ + -e "KONG_ADMIN_GUI_URL=http://localhost:8002" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 8001:8001 \ + -p 8444:8444 \ + -p 8002:8002 \ + -p 8445:8445 \ + -p 8003:8003 \ + -p 8004:8004 \ + kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```sh +docker run -d --name kong-gateway \ + --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_USER=kong" \ + -e "KONG_PG_PASSWORD=kongpass" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 127.0.0.1:8001:8001 \ + -p 127.0.0.1:8444:8444 \ + kong:{{page.releases_hash[page.version-index].ce-version}}-alpine + ``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ start_container | indent | replace: " ", "" }} + + Where: + * `--name` and `--network`: The name of the container to create, + and the Docker network it communicates on. + * [`KONG_DATABASE`](/gateway/{{page.release}}/reference/configuration/#database): + Specifies the type of database that Kong is using. + * [`KONG_PG_HOST`](/gateway/{{page.release}}/reference/configuration/#postgres-settings): + The name of the PostgreSQL Docker container that is communicating over the + `kong-net` network. + * [`KONG_PG_USER` and `KONG_PG_PASSWORD`](/gateway/{{page.release}}/reference/configuration/#postgres-settings): + The PostgreSQL username and password. {{site.base_gateway}} needs the login information + to store configuration data in the `KONG_PG_HOST` database. + * All [`_LOG`](/gateway/{{page.release}}/reference/configuration/#general-section) + parameters: set filepaths for the logs to output to, or use the values in + the example to print messages and errors to `stdout` and `stderr`. + * [`KONG_ADMIN_LISTEN`](/gateway/{{page.release}}/reference/configuration/#admin_listen): + The port that the Kong Admin API listens on for requests. + * [`KONG_ADMIN_GUI_URL`](/gateway/{{page.release}}/reference/configuration/#admin_gui_url): + (Enterprise only) The URL for accessing Kong Manager, preceded by a protocol + (for example, `http://`). + +1. Verify your installation: + + Access the `/services` endpoint using the Admin API: + + ```sh + curl -i -X GET --url http://localhost:8001/services + ``` + + You should receive a `200` status code. + +1. (Not available in OSS) Verify that Kong Manager is running by accessing it +using the URL specified in `KONG_ADMIN_GUI_URL`: + + ``` + http://localhost:8002 + ``` + +### Get started with {{site.base_gateway}} + +Now that you have a running Gateway instance, Kong provides a series of +[getting started guides](/gateway/{{page.release}}/get-started/comprehensive/) +to help you set up and enhance your first Service. + +In particular, right after installation you might want to: +* [Create a service and a route](/gateway/{{page.release}}/get-started/comprehensive/expose-services/) +* [Configure a plugin](/gateway/{{page.release}}/get-started/comprehensive/protect-services/) +* [Secure your services with authentication](/gateway/{{page.release}}/get-started/comprehensive/secure-services/) +* [Load balance traffic across targets](/gateway/{{page.release}}/get-started/comprehensive/load-balancing/) + +### Clean up containers + +If you're done testing {{site.base_gateway}} and no longer need the containers, you +can clean them up using the following commands: + +``` +docker kill kong-gateway +docker kill kong-database +docker container rm kong-gateway +docker container rm kong-database +docker network rm kong-net +``` + +## Install {{site.base_gateway}} in DB-less mode + +The following steps walk you through starting {{site.base_gateway}} in +[DB-less mode](/gateway/{{page.release}}/reference/db-less-and-declarative-config). + +### Create a Docker network + +Run the following command: + +```bash +docker network create kong-net +``` + +You can name this network anything you want. We use `kong-net` as +an example throughout this guide. + +This step is not strictly needed for running Kong in DB-less mode, but it is a good +precaution in case you want to add other things in the future (like a Rate Limiting plugin +backed up by a Redis cluster). + +### Prepare your configuration file + +1. Prepare your declarative configuration file in `.yml` or `.json` format. + + The syntax and properties are + described in the [Declarative Configuration format] guide. Add whatever core + entities (Services, Routes, Plugins, Consumers, etc) you need to this file. + + For example, a simple file with a Service and a Route + could look something like this: + + ```yaml + _format_version: "1.1" + _transform: true + + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: example_route + paths: + - /mock + strip_path: true + ``` + + This guide assumes you named the file `kong.yml`. + +1. Save your declarative configuration locally, and note the filepath. + +### Start {{site.base_gateway}} in DB-less mode + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + +1. From the same directory where you just created the `kong.yml` file, +run the following command to start a container with {{site.base_gateway}}: + +{% capture start_container %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```sh +docker run -d --name kong-dbless \ + --network=kong-net \ + -v "$(pwd):/kong/declarative/" \ + -e "KONG_DATABASE=off" \ + -e "KONG_DECLARATIVE_CONFIG=/kong/declarative/kong.yml" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \ + -e "KONG_ADMIN_GUI_URL=http://localhost:8002" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 8001:8001 \ + -p 8444:8444 \ + -p 8002:8002 \ + -p 8445:8445 \ + -p 8003:8003 \ + -p 8004:8004 \ + kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```sh +docker run -d --name kong-dbless \ + --network=kong-net \ + -v "$(pwd):/kong/declarative/" \ + -e "KONG_DATABASE=off" \ + -e "KONG_DECLARATIVE_CONFIG=/kong/declarative/kong.yml" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 127.0.0.1:8001:8001 \ + -p 127.0.0.1:8444:8444 \ + kong:{{page.releases_hash[page.version-index].ce-version}}-alpine + ``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ start_container | indent | replace: " ", "" }} + + Where: + * `--name` and `--network`: The name of the container to create, + and the Docker network it communicates on. + * `-v $(pwd):/path/to/target/`: Mount the current directory on your + local filesystem to a directory in the Docker container. This makes the + `kong.yml` file visible from the Docker container. + * [`KONG_DATABASE`](/gateway/{{page.release}}/reference/configuration/#database): + Sets the database to `off` to tell Kong not to use any + backing database for configuration storage. + * [`KONG_DECLARATIVE_CONFIG`](/gateway/{{page.release}}/reference/configuration/#declarative_config): + The path to a declarative configuration file inside the container. + This path should match the target path that you're mapping with `-v`. + * All [`_LOG`](/gateway/{{page.release}}/reference/configuration/#general-section) + parameters: set filepaths for the logs to output to, or use the values in + the example to print messages and errors to `stdout` and `stderr`. + * [`KONG_ADMIN_LISTEN`](/gateway/{{page.release}}/reference/configuration/#admin_listen): + The port that the Kong Admin API listens on for requests. + * [`KONG_ADMIN_GUI_URL`](/gateway/{{page.release}}/reference/configuration/#admin_gui_url): + (Enterprise only) The URL for accessing Kong Manager, preceded by a protocol + (for example, `http://`). + +1. Verify that {{site.base_gateway}} is running: + + ```sh + curl -i http://localhost:8001 + ``` + + Test an endpoint. For example, get a list of services: + + ```sh + curl -i http://localhost:8001/services + ``` + +[DB-less mode]: /gateway/{{page.release}}/reference/db-less-and-declarative-config/ +[Declarative Configuration format]: /gateway/{{page.release}}/reference/db-less-and-declarative-config/#the-declarative-configuration-format +[Docker Volume]: https://docs.docker.com/storage/volumes/ + +### Get started with {{site.base_gateway}} + +Now that you have a running Gateway instance, Kong provides a series of +[getting started guides](/gateway/{{page.release}}/get-started/comprehensive/) +to help you set up and enhance your first Service. + +If you use the sample `kong.yml` in this guide, you already have a Service and +a Route configured. Here are a few more things to check out: +* [Configure a plugin](/gateway/{{page.release}}/get-started/comprehensive/protect-services/?tab=using-deck-yaml/) +* [Secure your services with authentication](/gateway/{{page.release}}/get-started/comprehensive/secure-services/?tab=using-deck-yaml/) +* [Load balance traffic across targets](/gateway/{{page.release}}/get-started/comprehensive/load-balancing/?tab=using-deck-yaml/) + +### Clean up containers + +If you're done testing {{site.base_gateway}} and no longer need the containers, you +can clean them up using the following commands: + +``` +docker kill kong-dbless +docker container rm kong-dbless +docker network rm kong-net +``` + +## Troubleshooting + +If you did not receive a `200 OK` status code or need assistance completing +setup, reach out to your support contact or head over to the +[Support Portal](https://support.konghq.com/support/s/). diff --git a/app/gateway/2.6.x/install-and-run/helm.md b/app/gateway/2.6.x/install-and-run/helm.md new file mode 100644 index 000000000000..00fe3e13450d --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/helm.md @@ -0,0 +1,197 @@ +--- +title: Install on Kubernetes with Helm +--- + +This page explains how to install {{site.base_gateway}} with {{site.kic_product_name}} using Helm. + +* The Enterprise deployment includes a PostgreSQL sub-chart provided by Bitnami. +* For open-source deployments, you can choose to use the PostgreSQL sub-chart, or install without a database. + +Configuration for both options is flexible and depends on your environment. + +The documentation on installing with a [flat Kubernetes manifest](/gateway/{{page.release}}/install-and-run/kubernetes/) also explains how to install in DB-less mode for both Enterprise and OSS deployments. + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +- A Kubernetes cluster v1.19 or later +- `kubectl` v1.19 or later +- (Enterprise only) A `license.json` file from Kong +- Helm 3 + +## Create namespace + +Create the namespace for {{site.base_gateway}} with {{site.kic_product_name}}. For example: + +```sh +kubectl create namespace kong +``` + +## Set up Helm + +1. Add the Kong charts repository: + + ```sh + helm repo add kong https://charts.konghq.com + ``` + +1. Update Helm: + + ```sh + helm repo update + ``` + +## Create license secret +{:.badge .enterprise} + +1. Save your license file temporarily with the filename `license` (no file extension). + +1. Run: + + ```sh + kubectl create secret generic kong-enterprise-license --from-file=./license -n kong + ``` + +## Create secret for RBAC superuser (recommended) +{:.badge .enterprise} + +If you plan to use RBAC, you must create a secret for the superuser account password at this step in installation. You cannot create it later. + +1. Create the RBAC account. + +1. Create the secret: + + ```sh + kubectl create secret generic kong-enterprise-superuser-password \ + -n kong \ + --from-literal=password={YOUR_PASSWORD} + ``` + +## Create secret for Session plugin +{:.badge .enterprise} + +If you create an RBAC superuser and plan to work with Kong Manager or Dev Portal, you must also configure the Session plugin and store its config in a Kubernetes secret: + +1. Create a session config file for Kong Manager: + + ```bash + $ echo '{"cookie_name":"admin_session","cookie_samesite":"off","secret":"","cookie_secure":false,"storage":"kong"}' > admin_gui_session_conf + ``` + +1. Create a session config file for Kong Dev Portal: + + ```bash + $ echo '{"cookie_name":"portal_session","cookie_samesite":"off","secret":"","cookie_secure":false,"storage":"kong"}' > portal_session_conf + ``` + + Or, if you have different subdomains for the `portal_api_url` and `portal_gui_host`, set the `cookie_domain` + and `cookie_samesite` properties as follows: + + ``` + $ echo '{"cookie_name":"portal_session","cookie_samesite":"off","cookie_domain":"<.your_subdomain.com>","secret":"","cookie_secure":false,"storage":"kong"}' > portal_session_conf + ``` + +1. Create the secret: + + For Kong Manager only: + + ```sh + kubectl create secret generic kong-session-config \ + -n kong \ + --from-file=admin_gui_session_conf + ``` + + For Kong Manager and Dev Portal: + + ```sh + kubectl create secret generic kong-session-config \ + -n kong \ + --from-file=admin_gui_session_conf \ + --from-file=portal_session_conf + ``` + +## Create values.yaml file + +Create a `values.yaml` file to provide required values such as password secrets or optional email addresses for notifications. You can work from the [Enterprise example file](https://github.com/Kong/charts/blob/main/charts/kong/example-values/full-k4k8s-with-kong-enterprise.yaml). The example file includes comments to explain which values you must set. + +For OSS deployments, the default install might be sufficient, but you can explore other `values.yaml` files and [the readme in the charts repository](https://github.com/Kong/charts/blob/main/charts/kong/README.md), which includes an exhaustive list of all possible configuration properties. + +Note that the Enterprise deployment includes a PostgreSQL sub-chart provided by Bitnami. You might need to delete the PersistentVolume objects for PostgreSQL in your Kubernetes cluster to connect to the database after install. + +## Deploy {{site.base_gateway}} with {{site.kic_product_name}} + +1. Run: + + ```sh + ## {{site.base_gateway}} + helm install my-kong kong/kong -n kong --values ./values.yaml + ``` + + ```sh + ## {{site.base_gateway}} (OSS) + helm install kong/kong --generate-name --set ingressController.installCRDs=false + ``` + + For more information on working with Helm charts for {{site.ce_product_name}}, see the [chart documentation](https://github.com/Kong/charts/blob/main/charts/kong/README.md). + + This might take some time. + +1. Check pod status, and make sure the `my-kong-kong-{ID}` pod is running: + + ```bash + kubectl get pods -n kong + ``` + +## Finalize configuration and verify installation +{:.badge .enterprise} + +1. Run: + + ```sh + kubectl get svc my-kong-kong-admin \ + -n kong \ + --output=jsonpath='{.status.loadBalancer.ingress[0].ip}' + ``` + +1. Copy the IP address from the output, then add the following to the `.env` section of your `values.yaml` file: + + ```yaml + admin_api_uri: {YOUR-DNS-OR-IP} + ``` + + {:.note} + > **Note:** If you configure RBAC, you must specify a DNS hostname instead of an IP address. + +1. Clean up: + + ```sh + kubectl delete jobs -n kong --all + ``` + +1. Update with changed `values.yaml`: + + ``` + helm upgrade my-kong kong/kong -n kong --values ./values.yaml + ``` + +1. After the upgrade finishes, run: + + ``` + kubectl get svc -n kong + ``` + + With an Enterprise deployment, the output includes `EXTERNAL-IP` values for Kong Manager and Dev Portal. For example: + + ```sh + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + my-kong-kong-manager LoadBalancer 10.96.61.116 10.96.61.116 8002:31308/TCP,8445:32420/TCP 24m + my-kong-kong-portal LoadBalancer 10.101.251.123 10.101.251.123 8003:31609/TCP,8446:32002/TCP 24m + ``` + +## Next steps + +See the [{{site.kic_product_name}} docs](/kubernetes-ingress-controller/) for how-to guides, reference guides, and more. diff --git a/app/gateway/2.6.x/install-and-run/index.md b/app/gateway/2.6.x/install-and-run/index.md new file mode 100644 index 000000000000..025597e32494 --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/index.md @@ -0,0 +1,77 @@ +--- +title: Install Kong Gateway +disable_image_expand: true +--- + + + +### Deployment options + +{% include_cached /md/gateway/deployment-options.md release=page.release %} + +### Installation paths + +Some installation topics provide multiple package types and installation options. +Choose your preferred mode when following installation steps: + +* **Open-source**: Follow installation instructions and skip any Free or Enterprise steps. +* **Free Mode**: Install {{site.base_gateway}} without a license, gaining access to Kong Manager. +* **Enterprise**: Install {{site.base_gateway}} and add a license. + +If you install the {{site.base_gateway}} (not open-source), you can add a license +at any time to gain access to Enterprise features. + +{:.note} +> **Note**: For deployments on Kubernetes (including Helm and OpenShift), +you need to apply the license during installation. + +See [{{site.base_gateway}} Licensing](/gateway/latest/plan-and-deploy/licenses/) for a feature comparison +between Free Mode and the Enterprise subscription, and more information about licenses. diff --git a/app/gateway/2.6.x/install-and-run/kubernetes.md b/app/gateway/2.6.x/install-and-run/kubernetes.md new file mode 100644 index 000000000000..bae8541ac667 --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/kubernetes.md @@ -0,0 +1,109 @@ +--- +title: Install on Kubernetes +--- + +This page explains how to install {{site.base_gateway}} with {{site.kic_product_name}} in DB-less mode. To install with a database, see the documentation on installing with [Helm](/gateway/{{page.release}}/install-and-run/helm/). + +This page also includes the equivalent commands for OpenShift. + +Note that in DB-less mode on Kubernetes, config is stored in etcd, the Kubernetes native datastore. For more information see [Kubernetes Deployment Options](/gateway/{{page.release}}/plan-and-deploy/kubernetes-deployment-options/). + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +- A Kubernetes cluster v1.19 or later +- `kubectl` v1.19 or later +- (Enterprise only) A `license.json` file from Kong + +## Create namespace + +Create the namespace for {{site.base_gateway}} with {{site.kic_product_name}}. For example: + +```sh +## on Kubernetes native +kubectl create namespace kong +``` + +```sh +## on OpenShift +oc new-project kong +``` + +## Create license secret +{:.badge .enterprise} + +1. Save your license file temporarily with the filename `license` (no file extension). + +1. Run: + + ```sh + ## on Kubernetes native + kubectl create secret generic kong-enterprise-license --from-file=./license -n kong + ``` + + ```sh + ## on OpenShift + oc create secret generic kong-enterprise-license --from-file=./license -n kong + ``` + +## Deploy + +1. Run one of the following: + + ```sh + ## {{site.base_gateway}} on Kubernetes native + kubectl apply -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v{{site.data.kong_latest_KIC.version}}/deploy/single/all-in-one-dbless-k4k8s-enterprise.yaml + ``` + + ```sh + ## {{site.base_gateway}} on OpenShift + oc create -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v{{site.data.kong_latest_KIC.version}}/deploy/single/all-in-one-dbless-k4k8s-enterprise.yaml + ``` + + ```sh + ## {{site.base_gateway}} (OSS) on Kubernetes native + kubectl apply -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v{{site.data.kong_latest_KIC.version}}/deploy/single/all-in-one-dbless.yaml + ``` + + This might take a few minutes. + +1. Check the install status: + + ```sh + kubectl get pods -n kong + ``` + + or: + + ```sh + oc get pods -n kong + ``` + +1. To make HTTP requests, you need the IP address of the load balancer. Get the LoadBalancer address and store it in a local PROXY_IP environment variable: + + ```sh + export PROXY_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" service -n kong kong-proxy) + ``` + +1. Check that the value of $PROXY_IP is the value of the external host: + + ```sh + kubectl get service kong-proxy -n kong + ``` + + or: + + ```sh + oc get service kong-proxy -n kong + ``` + + {:.note} + > **Note:** Some cluster providers provide only a DNS name for load balancers. In this case, specify `.hostname` instead of `.ip`. + +## Next steps + +See the [{{site.kic_product_name}} docs](/kubernetes-ingress-controller/) for how-to guides, reference guides, and more. diff --git a/app/gateway/2.6.x/install-and-run/migrate-ce-to-ke.md b/app/gateway/2.6.x/install-and-run/migrate-ce-to-ke.md new file mode 100644 index 000000000000..5e41212ea04c --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/migrate-ce-to-ke.md @@ -0,0 +1,40 @@ +--- +title: Migrating from Kong Gateway (OSS) to Kong Gateway +toc: true +--- + +As of {{site.ee_product_name}} version 2.1.x and later, it is no longer necessary to explicitly +run the `migrate-community-to-enterprise` command parameter to migrate all +{{site.ce_product_name}} entities to {{site.ee_product_name}}. Running the `kong migrations` commands +performs that migration command on your behalf. + +{:.note} +> **Important:** You can only migrate to a {{site.ee_product_name}} version that +supports the same {{site.ce_product_name}} version. + +## Prerequisites + +{:.warning} +> **Warning:** This action is irreversible, therefore it is strongly + recommended to back up your production data before migrating from + {{site.ce_product_name}} to {{site.ee_product_name}}. + +* If running a version of {{site.ce_product_name}} earlier than 2.6.x, + [upgrade to Kong 2.6.x](/gateway/{{page.release}}/install-and-run/upgrade-oss/) before migrating + {{site.ce_product_name}} to {{site.ee_product_name}} 2.6.x. + +## Migration steps + +The following steps guide you through the migration process. + +1. Download {{site.ee_product_name}} 2.6.x and configure it to point to the + same datastore as your {{site.ce_product_name}} 2.6.x node. The migration + command expects the datastore to be up-to-date on any pending migration: + + ```shell + kong migrations up [-c configuration_file] + kong migrations finish [-c configuration_file] + ``` + +2. Confirm that all of the entities are now available on your + {{site.ee_product_name}} node. diff --git a/app/gateway/2.6.x/install-and-run/openshift.md b/app/gateway/2.6.x/install-and-run/openshift.md new file mode 100644 index 000000000000..dc7bf21c1c73 --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/openshift.md @@ -0,0 +1,179 @@ +--- +title: Install on OpenShift with Helm +badge: enterprise +--- + +This page explains how to install {{site.base_gateway}} with {{site.kic_product_name}} with a database. To install in DB-less mode, see the documentation on installing with a [flat Kubernetes manifest](/gateway/{{page.release}}/install-and-run/kubernetes/). + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + + +## Prerequisites + +- A Kubernetes cluster v1.19 or later +- `kubectl` v1.19 or later +- (Enterprise only) A `license.json` file from Kong +- Helm 3 + +## Create namespace + +Create the namespace for {{site.base_gateway}} with {{site.kic_product_name}}. For example: + +```sh +oc new-project kong +``` + +## Create license secret + +1. Save your license file temporarily with the filename `license` (no file extension). + +1. Run: + + ```sh + oc create secret generic kong-enterprise-license -n kong --from-file=./license + ``` + +## Set up Helm + +1. Add the Kong charts repository: + + ```sh + helm repo add kong https://charts.konghq.com + ``` + +1. Update Helm: + + ```sh + helm repo update + ``` + +## Create secret for RBAC superuser (recommended) +{:.badge .enterprise} + +If you plan to use RBAC, you must create the superuser account at this step in installation. You cannot create it later. + +1. Create the RBAC account. + +1. Create the secret: + + ```sh + oc create secret generic kong-enterprise-superuser-password \ + -n kong \ + --from-literal=password={your-password} + ``` + +## Create secret for Session plugin + +If you create an RBAC superuser and plan to work with Kong Manager or Dev Portal, you must also configure the Session plugin and store its config in a Kubernetes secret: + +1. Create a session config file for Kong Manager: + + ```bash + $ echo '{"cookie_name":"admin_session","cookie_samesite":"off","secret":"","cookie_secure":false,"storage":"kong"}' > admin_gui_session_conf + ``` + +1. Create a session config file for Kong Dev Portal: + + ```bash + $ echo '{"cookie_name":"portal_session","cookie_samesite":"off","secret":"","cookie_secure":false,"storage":"kong"}' > portal_session_conf + ``` + + Or, if you have different subdomains for the `portal_api_url` and `portal_gui_host`, set the `cookie_domain` + and `cookie_samesite` properties as follows: + + ``` + $ echo '{"cookie_name":"portal_session","cookie_samesite":"off","cookie_domain":"<.your_subdomain.com>","secret":"","cookie_secure":false,"storage":"kong"}' > portal_session_conf + ``` + +1. Create the secret: + + For Kong Manager only: + + ```sh + oc create secret generic kong-session-config \ + -n kong \ + --from-file=admin_gui_session_conf + ``` + + For Kong Manager and Dev Portal: + + ```sh + oc create secret generic kong-session-config \ + -n kong \ + --from-file=admin_gui_session_conf \ + --from-file=portal_session_conf + ``` + +## Create values.yaml file + +Create a `values.yaml` file to provide required values such as password secrets or optional email addresses for notifications. Work from the [Enterprise example file](https://github.com/Kong/charts/blob/main/charts/kong/example-values/full-k4k8s-with-kong-enterprise.yaml). The example file includes comments to explain which values you must set. The [readme in the charts repository](https://github.com/Kong/charts/blob/main/charts/kong/README.md) includes an exhaustive list of all possible configuration properties. + +Note that this deployment includes a PostgreSQL sub-chart provided by Bitnami. You might need to delete the PersistentVolume objects for PostgreSQL in your Kubernetes cluster to connect to the database after install. + +## Deploy {{site.base_gateway}} with {{site.kic_product_name}} + +1. Run: + + ```sh + helm install my-kong kong/kong -n kong --values ./values.yaml + ``` + + This might take some time. + +1. Check pod status, and make sure the `my-kong-kong-` pod is running: + + ```bash + oc get pods -n kong + ``` + +## Finalize configuration and verify installation + +1. Run: + + ```sh + oc get svc my-kong-kong-admin \ + -n kong \ + --output=jsonpath='{.status.loadBalancer.ingress[0].ip}' + ``` + +1. Copy the IP address from the output, then add the following to the `.env` section of your `values.yaml` file: + + ```yaml + admin_api_uri: + ``` + + {:.note} + > **Note:** If you configure RBAC, you must specify a DNS hostname instead of an IP address. + +1. Clean up: + + ```sh + oc delete jobs -n kong --all + ``` + +1. Update with changed `values.yaml`: + + ``` + helm upgrade my-kong kong/kong -n kong --values ./values.yaml + ``` + +1. After the upgrade finishes, run: + + ``` + oc get svc -n kong + ``` + + The output includes `EXTERNAL-IP` values for Kong Manager and Dev Portal. For example: + + ```sh + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + my-kong-kong-manager LoadBalancer 10.96.61.116 10.96.61.116 8002:31308/TCP,8445:32420/TCP 24m + my-kong-kong-portal LoadBalancer 10.101.251.123 10.101.251.123 8003:31609/TCP,8446:32002/TCP 24m + ``` + +## Next steps + +See the [{{site.kic_product_name}} docs](/kubernetes-ingress-controller/) for how-to guides, reference guides, and more. diff --git a/app/gateway/2.6.x/install-and-run/rhel.md b/app/gateway/2.6.x/install-and-run/rhel.md new file mode 100644 index 000000000000..74f87c258363 --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/rhel.md @@ -0,0 +1,111 @@ +--- +title: Install Kong Gateway on RHEL +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +Kong is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A [supported system](/gateway/{{page.release}}/compatibility/) with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* (Enterprise only) A `license.json` file from Kong + +## Download and Install + +You can install {{site.base_gateway}} by downloading an installation package or using our yum repository. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on RHEL from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/el/%{rhel}/noarch/kong-enterprise-edition-{{page.versions.ee}}.el%{rhel}.noarch.rpm) +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/el/%{rhel}/x86_64/kong-{{page.versions.ce}}.el%{rhel}.x86_64.rpm) + ``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package using `yum` or `rpm`. + + If you use the `rpm` install method, the packages _only_ contain {{site.base_gateway}}. They don't include any dependencies. + +{% capture install_package %} +{% navtabs %} +{% navtab yum %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}}.rpm +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}}.rpm +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endnavtab %} +{% navtab rpm %} + +{:.important} +> The `rpm` method is only available for open-source packages. For the `kong-enterprise-edition` package, use `yum`. + +```bash +rpm -iv kong-{{page.versions.ce}}.rpm +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + + Installing directly using `rpm` is suitable for Red Hat's [Universal Base Image](https://developers.redhat.com/blog/2020/03/24/red-hat-universal-base-images-for-docker-users) "minimal" variant. You will need to install Kong's dependencies separately via `microdnf`. + +{% endnavtab %} +{% navtab YUM repository %} + +Install the YUM repository from the command line. + +1. Download the Kong YUM repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.rpm.txt?distro=el&codename=$(rpm --eval '%{rhel}')" | sudo tee /etc/yum.repos.d/kong-gateway-legacy.repo + sudo yum -q makecache -y --disablerepo='*' --enablerepo='kong-gateway-legacy' + ``` + +2. Install Kong: +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}} +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}} +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.6.x/install-and-run/ubuntu.md b/app/gateway/2.6.x/install-and-run/ubuntu.md new file mode 100644 index 000000000000..55bb29988e51 --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/ubuntu.md @@ -0,0 +1,116 @@ +--- +title: Install Kong Gateway on Ubuntu +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +Kong is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A supported system with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* (Enterprise only) A `license.json` file from Kong + +## Download and install + +You can install {{site.base_gateway}} by downloading an installation package or using our APT repository. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on Ubuntu from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.all.deb "{{ site.links.direct }}/gateway-legacy/deb/ubuntu/pool/xenial/main/k/ko/kong-enterprise-edition_{{page.versions.ee}}/kong-enterprise-edition_{{page.versions.ee}}_all.deb" +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.all.deb "{{ site.links.direct }}/gateway-legacy/deb/ubuntu/pool/xenial/main/k/ko/kong_{{page.versions.ce}}/kong_{{page.versions.ce}}_amd64.deb" +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package: + +{% capture install_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo apt install -y ./kong-enterprise-edition-{{page.versions.ee}}.all.deb +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo apt install -y ./kong-{{page.versions.ce}}.all.deb +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + +{% endnavtab %} +{% navtab APT repository %} + +Install the APT repository from the command line. + +{% assign gpg_key = site.data.installation.gateway.legacy.gpg_key %} + +1. Setup the Kong APT repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/gpg.{{ gpg_key }}.key" | gpg --dearmor | sudo tee -a /usr/share/keyrings/kong-gateway-legacy-archive-keyring.gpg > /dev/null + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.deb.txt?distro=ubuntu&codename=xenial" | sudo tee /etc/apt/sources.list.d/kong-gateway-legacy.list > /dev/null + ``` + +2. Update the repository: + ```bash + sudo apt-get update + ``` + +3. Install Kong: + +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo apt install -y kong-enterprise-edition={{page.versions.ee}} +``` + +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo apt install -y kong={{page.versions.ce}} +``` + + +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% navtabs_ee %} +{% navtab Kong Gateway %} +{:.note .no-icon} +> Once {{ site.base_gateway }} is installed, you may want to run `sudo apt-mark hold kong-enterprise-edition`. This will prevent an accidental upgrade to a new version. +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +{:.note .no-icon} +> Once {{ site.base_gateway }} is installed, you may want to run `sudo apt-mark hold kong`. This will prevent an accidental upgrade to a new version. +{% endnavtab %} +{% endnavtabs_ee %} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.6.x/install-and-run/upgrade-enterprise.md b/app/gateway/2.6.x/install-and-run/upgrade-enterprise.md new file mode 100644 index 000000000000..6440a4f03c3a --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/upgrade-enterprise.md @@ -0,0 +1,217 @@ +--- +title: Upgrade Kong Gateway +badge: free +--- + +Upgrade to major, minor, and patch {{site.ee_product_name}} releases using the +`kong migrations` commands. + +You can also use the commands to migrate all {{site.ce_product_name}} entities +to {{site.ee_product_name}}. See +[Migrating from {{site.ce_product_name}} to {{site.base_gateway}}](/gateway/{{page.release}}/install-and-run/migrate-ce-to-ke/). + +If you experience any issues when running migrations, contact +[Kong Support](https://support.konghq.com/support/s/) for assistance. + +## Upgrade path for {{site.base_gateway}} releases + +Kong follows a structured approach to versioning its products, which makes a +distinction between major, minor, and patch versions. The upgrade +path for major and minor versions differs depending on the previous version +from which you are migrating: + +- Upgrading from 2.5.x to 2.6.x is a minor upgrade; however, read below for important +instructions on [database migration](#migrate-db), especially for Cassandra users. + +- Upgrading from 1.x is a major upgrade. Follow the [Version Prerequisites](#prereqs-v). +Be aware of any noted breaking changes as documented in the version to which you are upgrading. + +### Version prerequisites for migrating to {{site.base_gateway}} 2.6.x {#prereqs-v} + +If you are not on {{site.ee_product_name}} 2.5.x, you must first incrementally +upgrade to 2.5.x before upgrading to 2.6.x. Zero downtime is possible but _not_ +guaranteed if you are upgrading incrementally between versions, from 0.36.x to 1.3.x to +1.5.x to 2.1.x to 2.2.x to 2.3.x to 2.4.x to 2.5.x to 2.6.x., plan accordingly. + +* If running a version of {{site.ee_product_name}} earlier than 1.5, + [migrate to 1.5]({{site.links.archive}}/enterprise/1.5.x/deployment/migrations/) first. +* If running a version of {{site.ee_product_name}} earlier than 2.1, + [migrate to 2.1](/enterprise/2.1.x/deployment/upgrades/migrations/) first. +* If running a version of {{site.ee_product_name}} earlier than 2.2, + [migrate to 2.2](/enterprise/2.2.x/deployment/upgrades/migrations/) first. +* If running a version of {{site.ee_product_name}} earlier than 2.3, + [migrate to 2.3](/enterprise/2.3.x/deployment/upgrades/migrations/) first. +* If running a version of {{ site.ee_product_name }} earlier than 2.4, + [migrate to 2.4](/enterprise/2.4.x/deployment/upgrades/migrations/) first. +* If running a version of {{ site.ee_product_name }} earlier than 2.5, + [migrate to 2.5](/enterprise/2.5.x/deployment/upgrades/migrations/) first. + +### Dev Portal migrations + +There are no migrations necessary for the Dev Portal when upgrading from 2.5.x to +2.6.x. + +If you are currently using the Developer Portal in 1.5.x, it will no longer work without +[manually migrating files](/enterprise/2.1.x/developer-portal/latest-migrations) to version 2.1.x. + +### Upgrade considerations + +Before upgrading, review this list for any configuration or breaking changes that +affect your current installation. + +* If you are adding a new plugin to your installation, you need to run + `kong migrations up` with the plugin name specified. For example, + `KONG_PLUGINS=oauth2`. + +### Hybrid mode considerations + +{:.important} +> **Important:** If you are currently running in [hybrid mode](/gateway/{{page.release}}/plan-and-deploy/hybrid-mode/), +upgrade the Control Plane first, and then the Data Planes. + +* If you are currently running 2.6.x in classic (traditional) + mode and want to run in hybrid mode instead, follow the hybrid mode + [installation instructions](/gateway/{{page.release}}/plan-and-deploy/hybrid-mode/hybrid-mode-setup/) + after running the migration. +* Custom plugins (either your own plugins or third-party plugins that are not shipped with Kong) + need to be installed on both the Control Plane and the Data Planes in Hybrid mode. Install the + plugins on the Control Plane first, and then the Data Planes. +* The [Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced/) plugin does not + support the `cluster` strategy in hybrid mode. The `redis` strategy must be used instead. + +### Kong for Kubernetes considerations + +The Helm chart automates the upgrade migration process. When running `helm upgrade`, +the chart spawns an initial job to run `kong migrations up` and then spawns new +Kong pods with the updated version. Once these pods become ready, they begin processing +traffic and old pods are terminated. Once this is complete, the chart spawns another job +to run `kong migrations finish`. + +While the migrations themselves are automated, the chart does not automatically ensure +that you follow the recommended upgrade path. If you are upgrading from more than one minor +Kong version back, check the upgrade path recommendations for Kong open source or {{site.base_gateway}}. + +Although not required, users should upgrade their chart version and Kong version independently. +In the event of any issues, this will help clarify whether the issue stems from changes in +Kubernetes resources or changes in Kong. + +For specific Kong for Kubernetes version upgrade considerations, see +[Upgrade considerations](https://github.com/Kong/charts/blob/main/charts/kong/UPGRADE.md) + +#### Kong deployment split across multiple releases + +The standard chart upgrade automation process assumes that there is only a single Kong release +in the Kong cluster, and runs both `migrations up` and `migrations finish` jobs. + +If you split your Kong deployment across multiple Helm releases (to create proxy-only +and admin-only nodes, for example), you must set which migration jobs run based on your +upgrade order. + +To handle clusters split across multiple releases, you should: + +1. Upgrade one of the releases with: + + ```shell + helm upgrade RELEASENAME -f values.yaml \ + --set migrations.preUpgrade=true \ + --set migrations.postUpgrade=false + ``` +2. Upgrade all but one of the remaining releases with: + + ```shell + helm upgrade RELEASENAME -f values.yaml \ + --set migrations.preUpgrade=false \ + --set migrations.postUpgrade=false + ``` +3. Upgrade the final release with: + + ```shell + helm upgrade RELEASENAME -f values.yaml \ + --set migrations.preUpgrade=false \ + --set migrations.postUpgrade=true + ``` + +This ensures that all instances are using the new Kong package before running kong migrations finish. + +### Migrating databases for Upgrades {#migrate-db} + +{{site.ee_product_name}} supports the zero downtime migration model. This means +that while the migration is in process, you have two Kong clusters with different +versions running that are sharing the same database. This is sometimes referred +to as the +[blue-green migration model](https://en.wikipedia.org/wiki/Blue-green_deployment). + +The migrations are designed so that there is no need to fully copy +the data. The new version of {{site.ee_product_name}} is able to use the data as it +is migrated, and the old Kong cluster keeps working until it is finally time to +decommission it. For this reason, the full migration is split into two commands: + +- `kong migrations up`: performs only non-destructive operations +- `kong migrations finish`: puts the database in the final expected state (DB-less + mode is not supported in {{site.ee_product_name}}) + +#### PostgreSQL + +1. Download 2.6.x, and configure it to point to the same datastore as your old + 2.5.x (or 2.6.x-beta) cluster. +2. Run `kong migrations up`. +3. After that finishes running, both the old (2.5.x) and new (2.6.x) clusters can + now run simultaneously on the same datastore. Start provisioning 2.6.x nodes, + but do _not_ use their Admin API yet. + + {:.important} + > **Important:** If you need to make Admin API requests, + these should be made to the old cluster's nodes. This prevents + the new cluster from generating data that is not understood by the old + cluster. + +4. Gradually divert traffic away from your old nodes, and redirect traffic to + your 2.6.x cluster. Monitor your traffic to make sure everything + is going smoothly. +5. When your traffic is fully migrated to the 2.6.x cluster, decommission your + old 2.5.x (or 2.6.x-beta) nodes. +6. From your 2.6.x cluster, run `kong migrations finish`. From this point onward, + it is no longer possible to start nodes in the old 2.5.x (or 2.6.x-beta) cluster + that still points to the same datastore. Run this command _only_ when you are + confident that your migration was successful. From now on, you can safely make + Admin API requests to your 2.6.x nodes. + +#### Cassandra + +Due to internal changes, the table schemas used by {{site.ee_product_name}} 2.6.x on Cassandra +are incompatible with those used by {{site.ee_product_name}} 2.0.x. Migrating using the usual commands +`kong migrations up` and `kong migrations finish` will require a small +window of downtime, since the old and new versions cannot use the +database at the same time. Alternatively, to keep your previous version fully +operational while the new one initializes, you will need to transfer the +data to a new keyspace using a database dump, as described below: + +1. Download 2.6.x, and configure it to point to a new keyspace. + +2. Run `kong migrations bootstrap`. + + Once that finishes running, both the old (2.5.x) and new (2.6.x) + clusters can now run simultaneously, but the new cluster does not + have any data yet. +3. On the old cluster, run `kong config db_export`. This will create + a file named `kong.yml` with a database dump. +4. Transfer the file to the new cluster and run + `kong config db_import kong.yml`. This will load the data into the new cluster. +5. Gradually divert traffic away from your old nodes, and into + your 2.5.x cluster. Monitor your traffic to make sure everything + is going smoothly. +6. When your traffic is fully migrated to the 2.6.x cluster, + decommission your old nodes. + +### Installing 2.6.x on a fresh datastore + +For installing on a fresh datastore, {{site.ee_product_name}} 2.6.x has the +`kong migrations bootstrap` command. Run the following commands to +prepare a new 2.6.x cluster from a fresh datastore. By default, the `kong` CLI tool +loads the configuration from `/etc/kong/kong.conf`, but you can optionally use +the `-c` flag to indicate the path to your configuration file: + +```bash +$ kong migrations bootstrap [-c /path/to/kong.conf] +$ kong start [-c /path/to/kong.conf] +``` diff --git a/app/gateway/2.6.x/install-and-run/upgrade-oss.md b/app/gateway/2.6.x/install-and-run/upgrade-oss.md new file mode 100644 index 000000000000..7e5be07c3d48 --- /dev/null +++ b/app/gateway/2.6.x/install-and-run/upgrade-oss.md @@ -0,0 +1,167 @@ +--- +# Generated via autodoc/upgrading/generate.lua in the kong/kong repo +title: Upgrade Kong Gateway OSS +source_url: https://github.com/Kong/kong/blob/master/UPGRADE.md +--- + +This document guides you through the process of upgrading {{site.ce_product_name}} to the **latest version**. +To upgrade to prior versions, find the version number in the +[Upgrade doc in GitHub](https://github.com/Kong/kong/blob/master/UPGRADE.md). + +## Upgrade to 2.6.x + +Kong adopts a structured versioning approach, which makes a +distinction between "major", "minor", and "patch" versions. The upgrade path +will be different depending on which previous version from which you are migrating. + +If you are migrating from 2.0.x, 2.1.x, 2.2.x or 2.3.x, 2.4.x or 2.5.x into 2.6.x is a +minor upgrade, but read below for important instructions on database migration, +especially for Cassandra users. + +If you are migrating from 1.x, upgrading into 2.6.x is a major upgrade, +so, in addition, be aware of any [breaking changes](https://github.com/Kong/kong/blob/master/UPGRADE.md#breaking-changes-2.0) +between the 1.x and 2.x series below, further detailed in the +[CHANGELOG.md](https://github.com/Kong/kong/blob/2.0.0/CHANGELOG.md#200) document. + + +### Dependencies + +If you are using the provided binary packages, all necessary dependencies +for the gateway are bundled and you can skip this section. + +If you are building your dependencies by hand, there are changes since the +previous release, so you will need to rebuild them with the latest patches. + +The required OpenResty version for kong 2.6.x is +[1.19.9.1](https://openresty.org/en/changelog-1019003.html). This is more recent +than the version in Kong 2.5.0 (which used `1.19.3.2`). In addition to an upgraded +OpenResty, you will need the correct [OpenResty patches](https://github.com/Kong/kong-build-tools/tree/master/openresty-patches) +for this new version, including the latest release of [lua-kong-nginx-module](https://github.com/Kong/lua-kong-nginx-module). +The [kong-build-tools](https://github.com/Kong/kong-build-tools) +repository contains [openresty-build-tools](https://github.com/Kong/kong-build-tools/tree/master/openresty-build-tools), +which allows you to more easily build OpenResty with the necessary patches and modules. + +There is a new way to deploy Go using Plugin Servers. +For more information, see [Developing Go plugins](/gateway/{{page.release}}/reference/external-plugins/#developing-go-plugins). + +### Template changes + +There are **Changes in the Nginx configuration file**, between kong 2.0.x, +2.1.x, 2.2.x, 2.3.x, 2.4.x and 2.5.x. + +To view the configuration changes between versions, clone the +[Kong repository](https://github.com/kong/kong) and run `git diff` +on the configuration templates, using `-w` for greater readability. + +Here's how to see the differences between previous versions and 2.6.x: + +``` +git clone https://github.com/kong/kong +cd kong +git diff -w 2.0.0 2.6.0 kong/templates/nginx_kong*.lua +``` + +**Note:** Adjust the starting version number +(2.0.x, 2.1.x, 2.2.x, 2.3.x, 2.4.x or 2.5.x) to the version number you are currently using. + +To produce a patch file, use the following command: + +``` +git diff 2.0.0 2.6.0 kong/templates/nginx_kong*.lua > kong_config_changes.diff +``` + +**Note:** Adjust the starting version number +(2.0.x, 2.1.x, 2.2.x, 2.3.x, 2.4.x or 2.5.x) to the version number you are currently using. + + +### Suggested upgrade path + +**Version prerequisites for migrating to version 2.6.x** + +The lowest version that Kong 2.6.x supports migrating from is 1.0.x. +If you are migrating from a version lower than 0.14.1, you need to +migrate to 0.14.1 first. Then, once you are migrating from 0.14.1, +please migrate to 1.5.x first. + +The steps for upgrading from 0.14.1 to 1.5.x are the same as upgrading +from 0.14.1 to Kong 1.0. Please follow the steps described in the +"Migration Steps from 0.14" in the + +[Suggested Upgrade Path for Kong 1.0](https://github.com/Kong/kong/blob/master/UPGRADE.md#kong-1-0-upgrade-path) +with the addition of the `kong migrations migrate-apis` command, +which you can use to migrate legacy `apis` configurations. + +Once you migrated to 1.5.x, you can follow the instructions in the section +below to migrate to 2.6.x. + +### Upgrade from 1.0.x - 2.5.x to 2.6.x + +**PostgreSQL** + +Kong 2.6.x supports a no-downtime migration model. This means that while the +migration is ongoing, you will have two Kong clusters running, sharing the +same database. (This is sometimes called the Blue/Green migration model.) + +The migrations are designed so that the new version of Kong is able to use +the database as it is migrated while the old Kong cluster keeps working until +it is time to decommission it. For this reason, the migration is split into +two steps, performed via commands `kong migrations up` (which does +only non-destructive operations) and `kong migrations finish` (which puts the +database in the final expected state for Kong 2.6.x). + +1. Download 2.6.x, and configure it to point to the same datastore + as your old (1.0 to 2.0) cluster. Run `kong migrations up`. +2. After that finishes running, both the old (2.x.x) and new (2.6.x) + clusters can now run simultaneously. Start provisioning 2.6.x nodes, + but do not use their Admin API yet. If you need to perform Admin API + requests, these should be made to the old cluster's nodes. The reason + is to prevent the new cluster from generating data that is not understood + by the old cluster. +3. Gradually divert traffic away from your old nodes, and into + your 2.6.x cluster. Monitor your traffic to make sure everything + is going smoothly. +4. When your traffic is fully migrated to the 2.6.x cluster, + decommission your old nodes. +5. From your 2.6.x cluster, run: `kong migrations finish`. + From this point on, it will not be possible to start + nodes in the old cluster 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 2.6.x nodes. + +**Cassandra** + +Due to internal changes, the table schemas used by Kong 2.6.x on Cassandra +are incompatible with those used by Kong 2.1.x (or lower). Migrating using the usual commands +`kong migrations up` and `kong migrations finish` will require a small +window of downtime, since the old and new versions cannot use the +database at the same time. Alternatively, to keep your previous version fully +operational while the new one initializes, you will need to transfer the +data to a new keyspace via a database dump, as described below: + +1. Download 2.6.x, and configure it to point to a new keyspace. + Run `kong migrations bootstrap`. +2. Once that finishes running, both the old (pre-2.1) and new (2.6.x) + clusters can now run simultaneously, but the new cluster does not + have any data yet. +3. On the old cluster, run `kong config db_export`. This will create + a file `kong.yml` with a database dump. +4. Transfer the file to the new cluster and run + `kong config db_import kong.yml`. This will load the data into the new cluster. +5. Gradually divert traffic away from your old nodes, and into + your 2.6.x cluster. Monitor your traffic to make sure everything + is going smoothly. +6. When your traffic is fully migrated to the 2.6.x cluster, + decommission your old nodes. + +### Installing 2.6.x on a fresh datastore + +The following commands should be used to prepare a new 2.6.x cluster from a +fresh datastore. By default the `kong` CLI tool will load the configuration +from `/etc/kong/kong.conf`, but you can optionally use the flag `-c` to +indicate the path to your configuration file: + +``` +kong migrations bootstrap [-c /path/to/your/kong.conf] +kong start [-c /path/to/your/kong.conf] +``` diff --git a/app/gateway/2.6.x/pdk/index.md b/app/gateway/2.6.x/pdk/index.md new file mode 100644 index 000000000000..bab1f696140a --- /dev/null +++ b/app/gateway/2.6.x/pdk/index.md @@ -0,0 +1,182 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: PDK +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + +## 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) -- "2.0.0" +``` + +[Back to top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) diff --git a/app/gateway/2.6.x/pdk/kong.client.md b/app/gateway/2.6.x/pdk/kong.client.md new file mode 100644 index 000000000000..f1af97d033b4 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.client.md @@ -0,0 +1,303 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.client +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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, response, 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 top](#kongclient) + + +### 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](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/configuration/#real_ip_recursive) + + +**Phases** + +* certificate, rewrite, access, header_filter, response, 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.client.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 top](#kongclient) + + +### 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, response, 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 top](#kongclient) + + +### 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](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/configuration/#real_ip_recursive) + +**Phases** + +* certificate, rewrite, access, header_filter, response, 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 top](#kongclient) + + +### kong.client.get_credential() + +Returns the credentials of the currently authenticated consumer. + If not set yet, it returns `nil`. + +**Phases** + +* access, header_filter, response, body_filter, log + +**Returns** + +* `string` 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 top](#kongclient) + + +### kong.client.load_consumer(consumer_id[, search_by_username.]) + +Returns the consumer from the datastore. + Will look up the consumer by id, and optionally will do a second search by name. + +**Phases** + +* access, header_filter, response, body_filter, log + +**Parameters** + +* **consumer_id** (string): The consumer id to look up. +* **search_by_username.** (boolean, _optional_): If truthy, + then if the consumer was not found by id, + then a second search by username will be performed + +**Returns** + +1. `table|nil` consumer entity or nil + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +local consumer_id = "john_doe" +local consumer = kong.client.load_consumer(consumer_id, true) +``` + +[Back to top](#kongclient) + + +### kong.client.get_consumer() + +Returns the `consumer` entity of the currently authenticated consumer. + If not set yet, it returns `nil`. + +**Phases** + +* access, header_filter, response, 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 top](#kongclient) + + +### 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 top](#kongclient) + + +### kong.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, response, body_filter, log + +**Parameters** + +* **allow_terminated.** (boolean, _optional_): If set, the `X-Forwarded-Proto` header will be checked when checking for https + +**Returns** + +1. `string|nil` `"http"`, `"https"`, `"tcp"`, `"tls"` or `nil` + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +kong.client.get_protocol() -- "http" +``` + +[Back to top](#kongclient) diff --git a/app/gateway/2.6.x/pdk/kong.client.tls.md b/app/gateway/2.6.x/pdk/kong.client.tls.md new file mode 100644 index 000000000000..befa7295ec59 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.client.tls.md @@ -0,0 +1,148 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.client.tls +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## kong.client.tls + +The client.tls module provides functions for interacting with TLS + connections from client. + + + +### kong.client.tls.request_client_certificate() + +Requests client to present its client-side certificate to initiate mutual + TLS authentication between server and client. + + This function only *requests*, but does not *require* the client to start + the mTLS process. Even if the client did not present a client certificate + the TLS handshake will still complete (obviously not being mTLS in that + case). Whether the client honored the request can be determined using + get_full_client_certificate_chain in later phases. + + +**Phases** + +* certificate + +**Returns** + +1. `true|nil` true if request was received, nil if request failed + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +local res, err = kong.client.tls.request_client_certificate() +if not res then + -- do something with err +end +``` + +[Back to top](#kongclienttls) + + +### kong.client.tls.disable_session_reuse() + +Prevents the TLS session for the current connection from being reused + by disabling session ticket and session ID for the current TLS connection. + +**Phases** + +* certificate + +**Returns** + +1. `true|nil` true if success, nil if failed + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +local res, err = kong.client.tls.disable_session_reuse() +if not res then + -- do something with err +end +``` + +[Back to top](#kongclienttls) + + +### kong.client.tls.get_full_client_certificate_chain() + +Returns the PEM encoded downstream client certificate chain with the + client certificate at the top and intermediate certificates + (if any) at the bottom. + +**Phases** + +* rewrite, access, balancer, header_filter, body_filter, log + +**Returns** + +1. `string|nil` PEM-encoded client certificate if mTLS handshake + was completed, nil if an error occurred or client did not present + its certificate + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +local cert, err = kong.client.get_full_client_certificate_chain() +if err then + -- do something with err +end + +if not cert then + -- client did not complete mTLS +end + +-- do something with cert +``` + +[Back to top](#kongclienttls) + + +### kong.client.tls.set_client_verify() + +Overrides client verify result generated by the log serializer. + + By default, the `request.tls.client_verify` field inside the log + generated by Kong's log serializer is the same as the + [$ssl_client_verify](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_client_verify) + Nginx variable. + + Only "SUCCESS", "NONE" or "FAILED:" are accepted values. + + This function does not return anything on success, and throws an Lua error + in case of failures. + + +**Phases** + +* rewrite, access, balancer + +**Usage** + +``` lua +kong.client.tls.set_client_verify("FAILED:unknown CA") +``` + +[Back to top](#kongclienttls) diff --git a/app/gateway/2.6.x/pdk/kong.cluster.md b/app/gateway/2.6.x/pdk/kong.cluster.md new file mode 100644 index 000000000000..43493f8ab7b3 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.cluster.md @@ -0,0 +1,56 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.cluster +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## kong.cluster + +Cluster-level utilities + + + +### kong.cluster.get_id() + +Returns the unique id for this Kong cluster. If Kong + is running in DB-less mode without a cluster ID explicitly defined, + then this method returns nil. + + For Hybrid mode, all Control Planes and Data Planes belonging to the same + cluster returns the same cluster ID. For traditional database based + deployments, all Kong nodes pointing to the same database will also return + the same cluster ID. + + +**Returns** + +1. `string|nil` The v4 UUID used by this cluster as its id + +1. `string|nil` an error message + + +**Usage** + +``` lua +local id, err = kong.cluster.get_id() +if err then + -- handle error +end + +if not id then + -- no cluster ID is available +end + +-- use id here +``` + +[Back to top](#kongcluster) diff --git a/app/gateway/2.6.x/pdk/kong.ctx.md b/app/gateway/2.6.x/pdk/kong.ctx.md new file mode 100644 index 000000000000..ad17f5903db3 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.ctx.md @@ -0,0 +1,115 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.ctx +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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`, `response`, `body_filter`, `log`, and `preread` 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, response, body_filter, log, preread + +**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 top](#kongctx) + + +### 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 overwriting 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`, `log`, and `preread` 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, response, body_filter, log, preread + +**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 top](#kongctx) diff --git a/app/gateway/2.6.x/pdk/kong.ip.md b/app/gateway/2.6.x/pdk/kong.ip.md new file mode 100644 index 000000000000..4a67218de322 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.ip.md @@ -0,0 +1,59 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.ip +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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](/gateway/latest/reference/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, response, 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 top](#kongip) diff --git a/app/gateway/2.6.x/pdk/kong.log.md b/app/gateway/2.6.x/pdk/kong.log.md new file mode 100644 index 000000000000..33efaddd85d6 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.log.md @@ -0,0 +1,390 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# TODO FOR SINGLE-SOURCING: check against latest from OSS +# Per Slack thread at https://kongstrong.slack.com/archives/CDSTDSG9J/p1634045626111200 +# +title: kong.log +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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: + + ```plaintext + [kong] %file_src:%line_src %message + ``` + + In comparison, log lines produced by plugins have the following format: + + ```plaintext + [kong] %file_src:%line_src [%namespace] %message + ``` + + Where: + + * `%namespace`: is the configured namespace (the plugin name in this case). + * `%file_src`: is the filename 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: + + ```plaintext + 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: + + ```plaintext + 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, response, 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 top](#konglog) + + +### 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: + + ```plaintext + 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: + + ```plaintext + 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, response, 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 top](#konglog) + + +### 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. + + 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: + + ```plaintext + %file_src:%func_name:%line_src %message + ``` + + Where: + + * `%file_src`: is the filename 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, response, 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 top](#konglog) + + +### 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, response, body_filter, log + +**Usage** + +``` lua +kong.log.inspect.on() +``` + +[Back to top](#konglog) + + +### 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, response, body_filter, log + +**Usage** + +``` lua +kong.log.inspect.off() +``` + +[Back to top](#konglog) + + +### kong.log.set_serialize_value(key, value, options) + +Sets a value to be used on the `serialize` custom table + + Logging plugins use the output of `kong.log.serialize()` as a base for their logs. + + This function allows customizing such output. + + It can be used to replace existing values on the output. + It can be used to delete existing values by passing `nil`. + + Note: the type checking of the `value` parameter can take some time so + it is deferred to the `serialize()` call, which happens in the log + phase in most real-usage cases. + + +**Phases** + +* certificate, rewrite, access, header_filter, response, body_filter, log + +**Parameters** + +* **key** (string): the name of the field. +* **value** (number|string|boolean|table): value to be set. When a table is used, its keys must be numbers, strings, booleans, and its values can be numbers, strings or other tables like itself, recursively. +* **options** (table): can contain two entries: options.mode can be `set` (the default, always sets), `add` (only add if entry does not already exist) and `replace` (only change value if it already exists). + +**Returns** + +* `table` the request information table + + +**Usage** + +``` lua +-- Adds a new value to the serialized table +kong.log.set_serialize_value("my_new_value", 1) +assert(kong.log.serialize().my_new_value == 1) + +-- Value can be a table +kong.log.set_serialize_value("my", { new = { value = 2 } }) +assert(kong.log.serialize().my.new.value == 2) + +-- It is possible to change an existing serialized value +kong.log.set_serialize_value("my_new_value", 3) +assert(kong.log.serialize().my_new_value == 3) + +-- Unset an existing value by setting it to nil +kong.log.set_serialize_value("my_new_value", nil) +assert(kong.log.serialize().my_new_value == nil) + +-- Dots in the key are interpreted as table accesses +kong.log.set_serialize_value("my.new.value", 4) +assert(kong.log.serialize().my.new_value == 4) +``` + +[Back to top](#konglog) + + +### kong.log.serialize() + +Generates a table that contains information that are helpful for logging. + + This method can currently be used in the `http` subsystem. + + The following fields are included in the returned table: + * `client_ip` - client IP address in textual format. + * `latencies` - request/proxy latencies. + * `request.headers` - request headers. + * `request.method` - request method. + * `request.querystring` - request query strings. + * `request.size` - size of request. + * `request.url` and `request.uri` - URL and URI of request. + * `response.headers` - response headers. + * `response.size` - size of response. + * `response.status` - response HTTP status code. + * `route` - route object matched. + * `service` - service object used. + * `started_at` - timestamp this request came in, in milliseconds. + * `tries` - Upstream information; this is an array and if any balancer retries occurred, will contain more than one entry. + * `upstream_uri` - request URI sent to Upstream. + + The following fields are only present in an authenticated request (with consumer): + + * `authenticated_entity` - credential used for authentication. + * `consumer` - consumer entity accessing the resource. + + The following fields are only present in a TLS/HTTPS request: + * `request.tls.version` - TLS/SSL version used by the connection. + * `request.tls.cipher` - TLS/SSL cipher used by the connection. + * `request.tls.client_verify` - mTLS validation result. Contents are the same as described in [$ssl_client_verify](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_client_verify). + + **Warning:** This function may return sensitive data (e.g., API keys). + Consider filtering before writing it to unsecured locations. + + All fields in the returned table may be altered via kong.log.set_serialize_value + + The following http authentication headers are redacted by default, if they appear in the request: + * `request.headers.authorization` + * `request.headers.proxy-authorization` + + To see what content is present in your setup, enable any of the logging + plugins (e.g., `file-log`) and the output written to the log file is the table + returned by this function JSON-encoded. + + +**Phases** + +* log + +**Returns** + +* `table` the request information table + + +**Usage** + +``` lua +kong.log.serialize() +``` + +[Back to top](#konglog) diff --git a/app/gateway/2.6.x/pdk/kong.nginx.md b/app/gateway/2.6.x/pdk/kong.nginx.md new file mode 100644 index 000000000000..b0e481fdf14d --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.nginx.md @@ -0,0 +1,44 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.nginx +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## kong.nginx + +Nginx information module + A set of functions allowing to retrieve Nginx-specific implementation + details and meta information. + + + +### kong.nginx.get_subsystem() + +Returns the current Nginx subsystem this function is called from: "http" + or "stream". + +**Phases** + +* any + +**Returns** + +* `string` subsystem Either `"http"` or `"stream"` + + +**Usage** + +``` lua +kong.nginx.get_subsystem() -- "http" +``` + +[Back to top](#kongnginx) diff --git a/app/gateway/2.6.x/pdk/kong.node.md b/app/gateway/2.6.x/pdk/kong.node.md new file mode 100644 index 000000000000..a3586ff5c605 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.node.md @@ -0,0 +1,131 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.node +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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 top](#kongnode) + + +### kong.node.get_memory_stats([unit[, scale]]) + +Returns memory usage statistics about this node. + +**Parameters** + +* **unit** (string, _optional_): The unit memory should be reported in. Can be + either of `b/B`, `k/K`, `m/M`, or `g/G` for bytes, kibibytes, mebibytes, + or gibibytes, respectively. Defaults to `b` (bytes). +* **scale** (number, _optional_): The number of digits to the right of the decimal + point. Defaults to 2. + +**Returns** + +* `table` A table containing memory usage statistics for this node. + If `unit` is `b/B` (the default) reported values will be Lua numbers. + Otherwise, reported values will be a string with the unit as a suffix. + + +**Usage** + +``` lua +local res = kong.node.get_memory_stats() +-- res will have the following structure: +{ + lua_shared_dicts = { + kong = { + allocated_slabs = 12288, + capacity = 24576 + }, + kong_db_cache = { + allocated_slabs = 12288, + capacity = 12288 + } + }, + workers_lua_vms = { + { + http_allocated_gc = 1102, + pid = 18004 + }, + { + http_allocated_gc = 1102, + pid = 18005 + } + } +} + +local res = kong.node.get_memory_stats("k", 1) +-- res will have the following structure: +{ + lua_shared_dicts = { + kong = { + allocated_slabs = "12.0 KiB", + capacity = "24.0 KiB", + }, + kong_db_cache = { + allocated_slabs = "12.0 KiB", + capacity = "12.0 KiB", + } + }, + workers_lua_vms = { + { + http_allocated_gc = "1.1 KiB", + pid = 18004 + }, + { + http_allocated_gc = "1.1 KiB", + pid = 18005 + } + } +} +``` + +[Back to top](#kongnode) + + +### kong.node.get_hostname() + +Returns the name used by the local machine + +**Returns** + +* `string` The local machine hostname + + +**Usage** + +``` lua +local hostname = kong.node.get_hostname() +``` + +[Back to top](#kongnode) diff --git a/app/gateway/2.6.x/pdk/kong.request.md b/app/gateway/2.6.x/pdk/kong.request.md new file mode 100644 index 000000000000..c4e29eb14178 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.request.md @@ -0,0 +1,688 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.request +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/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, response, body_filter, log, admin_api + +**Returns** + +* `string` the forwarded scheme + + +**Usage** + +``` lua +kong.request.get_forwarded_scheme() -- "https" +``` + +[Back to top](#kongrequest) + + +### 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-Host` or not depends on + several Kong configuration parameters: + + * [trusted\_ips](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/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, response, body_filter, log, admin_api + +**Returns** + +* `string` the forwarded host + + +**Usage** + +``` lua +kong.request.get_forwarded_host() -- "example.com" +``` + +[Back to top](#kongrequest) + + +### kong.request.get_forwarded_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](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/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. + + When running Kong behind the L4 port mapping (or forwarding) you can also + configure: + * [port\_maps](/gateway/latest/reference/configuration/#port_maps) + + `port_maps` configuration parameter enables this function to return the + port to which the port Kong is listening to is mapped to (in case they differ). + + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `number` the forwarded port + + +**Usage** + +``` lua +kong.request.get_forwarded_port() -- 1234 +``` + +[Back to top](#kongrequest) + + +### kong.request.get_forwarded_path() + +Returns the path component of the request's URL, but also considers + `X-Forwarded-Path` if it comes from a trusted source. The value + is returned as a Lua string. + + Whether this function considers `X-Forwarded-Path` or not depends on + several Kong configuration parameters: + + * [trusted\_ips](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/configuration/#real_ip_recursive) + + **Note**: we do not currently do any normalization on the request path. + + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `string` the forwarded path + + +**Usage** + +``` lua +kong.request.get_forwarded_path() -- /path +``` + +[Back to top](#kongrequest) + + +### kong.request.get_forwarded_prefix() + +Returns the prefix path component of the request's URL that Kong stripped + before proxying to upstream. It also checks if `X-Forwarded-Prefix` comes + from a trusted source, and uses it as is when given. The value is returned + as a Lua string. + + If a trusted `X-Forwarded-Prefix` is not passed, this function must be called after Kong has ran its router (`access` phase), + as the Kong router may strip the prefix of the request path. That stripped + path will become the return value of this function, unless there was already + a trusted `X-Forwarded-Prefix` header in the request. + + Whether this function considers `X-Forwarded-Prefix` or not depends on + several Kong configuration parameters: + + * [trusted\_ips](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/configuration/#real_ip_recursive) + + **Note**: we do not currently do any normalization on the request path prefix. + + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `string|nil` the forwarded path prefix or nil if prefix was not stripped + + +**Usage** + +``` lua +kong.request.get_forwarded_prefix() -- /prefix +``` + +[Back to top](#kongrequest) + + +### kong.request.get_http_version() + +Returns the HTTP version used by the client in the request as a Lua + number, returning values such as `1`, `1.1`, `2.0`, or `nil` for + unrecognized values. + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `number|nil` the HTTP version as a Lua number + + +**Usage** + +``` lua +kong.request.get_http_version() -- 1.1 +``` + +[Back to top](#kongrequest) + + +### kong.request.get_method() + +Returns the HTTP method of the request. The value is normalized to + upper-case. + + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `string` the request method + + +**Usage** + +``` lua +kong.request.get_method() -- "GET" +``` + +[Back to top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### kong.request.get_path_with_query() + +Returns the path, including the querystring if any. No + transformations/normalizations are done. + + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) diff --git a/app/gateway/2.6.x/pdk/kong.response.md b/app/gateway/2.6.x/pdk/kong.response.md new file mode 100644 index 000000000000..c83a32378998 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.response.md @@ -0,0 +1,568 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.response +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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, response, 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 top](#kongresponse) + + +### 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, response, 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 top](#kongresponse) + + +### 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, response, 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 top](#kongresponse) + + +### 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, response, 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 top](#kongresponse) + + +### kong.response.set_status(status) + +Allows changing the downstream response HTTP status code before sending it + to the client. + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongresponse) + + +### kong.response.set_header(name, value) + +Sets a response header with the given value. This function overrides any + existing header with the same name. + + Note: Underscores in Header names are automatically transformed into dashes + by default. If you want to deactivate this behavior you should set + the `lua_transform_underscores_in_response_headers` nginx config option to `off` + + This setting can be set in the Kong Config file: + + nginx_http_lua_transform_underscores_in_response_headers = off + + Be aware that changing this setting might slightly break any plugins that + rely on the automatic underscore conversion. + + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongresponse) + + +### 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().` + + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongresponse) + + +### kong.response.clear_header(name) + +Removes all occurrences of the specified header in the response sent to + the client. + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongresponse) + + +### 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. + + 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, response, 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 top](#kongresponse) + + +### 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. + + **In L4 proxy mode**, **only** the following status code are supported: + + * 200 - OK + * 400 - Bad request + * 403 - Forbidden + * 500 - Internal server error + * 502 - Bad gateway + * 503 - Service unavailable + + For **L4 proxy mode** the `status` code provided is primarily for logging + and statistical purpose, and is not visible to the client directly. + + 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. On gRPC we cannot send + the `body` with this function at the moment at least, so what it does + instead is that it sends "body" in `grpc-message` header instead. If the + body is a table it looks for a field `message` in it, and uses that as a + `grpc-message` header. Though, if you have specified `Content-Type` header + starting with `application/grpc`, the body will be sent. + + **In L4 proxy mode**, `body` can only be `nil` or a string. Automatic JSON + encoding is not available. When provided, depends on the value of `status`, + the following will happen: + + When `status` is 500, 502 or 503, then `body` will be logged in the Kong + error log file. Otherwise `body` will be sent back to the L4 client. + + 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()`. This argument is ignored in L4 proxy mode. + + Unless manually specified, this method will automatically set the + Content-Length header in the produced response for convenience. + +**Phases** + +* preread, 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" +}) + +--- + +-- In L4 proxy mode +return kong.response.exit(200, "Success") +``` + +[Back to top](#kongresponse) + + +### kong.response.error(status[, message[, headers]]) + +This function interrupts the current processing and produces an error + response. + + It is recommended to use this function in conjunction with the `return` + operator, to better reflect its meaning: + + ```lua + return kong.response.error(500, "Error", {["Content-Type"] = "text/html"}) + ``` + + The first argument `status` will set the status code of the response that + will be seen by the client. The status code must be of an error, i.e. + >399. + + The second, optional, `message` argument will set the message describing + the error, which will be written in the body. + + 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()`. + + This method will send the response formatted in JSON, XML, HTML or plain + text. The actual format is chosen using one of the following options: + - Manually specifying in `headers` argument using the `Content-Type` + header. + - Conform to the `Accept` header from the request. + - If none of the above is found, fallback to JSON format. + 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 (>399) +* **message** (string, _optional_): The error message to be used +* **headers** (table, _optional_): The headers to be used + +**Returns** + +* Nothing; throws an error on invalid input. + + +**Usage** + +``` lua +return kong.response.error(403, "Access Forbidden", { + ["Content-Type"] = "text/plain", + ["WWW-Authenticate"] = "Basic" +}) + +--- + +return kong.response.error(403, "Access Forbidden") + +--- + +return kong.response.error(403) +``` + +[Back to top](#kongresponse) diff --git a/app/gateway/2.6.x/pdk/kong.router.md b/app/gateway/2.6.x/pdk/kong.router.md new file mode 100644 index 000000000000..66b0bae6b63c --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.router.md @@ -0,0 +1,73 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.router +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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, response, body_filter, log + +**Returns** + +* `table` the `route` entity. + + +**Usage** + +``` lua +local route = kong.router.get_route() +local protocols = route.protocols +``` + +[Back to top](#kongrouter) + + +### kong.router.get_service() + +Returns the current `service` entity. The request will be targeted to this + upstream service. + + +**Phases** + +* access, header_filter, response, 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 route without a service +end +``` + +[Back to top](#kongrouter) diff --git a/app/gateway/2.6.x/pdk/kong.service.md b/app/gateway/2.6.x/pdk/kong.service.md new file mode 100644 index 000000000000..b140c6297628 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.service.md @@ -0,0 +1,258 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.service +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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 + health checking. + + + +### 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 top](#kongservice) + + +### 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 top](#kongservice) + + +### kong.service.set_tls_cert_key(chain, key) + +Sets the client certificate used while handshaking with the Service. + + The `chain` argument is the client certificate and intermediate chain (if any) + returned by functions such as [ngx.ssl.parse\_pem\_cert](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_cert). + + The `key` argument is the private key corresponding to the client certificate + returned by functions such as [ngx.ssl.parse\_pem\_priv\_key](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_priv_key). + + +**Phases** + +* `rewrite`, `access`, `balancer` + +**Parameters** + +* **chain** (cdata): The client certificate chain +* **key** (cdata): The client certificate private key + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one + + +**Usage** + +``` lua +local chain = assert(ssl.parse_pem_cert(cert_data)) +local key = assert(ssl.parse_pem_priv_key(key_data)) + +local ok, err = kong.service.set_tls_cert_key(chain, key) +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservice) + + +### kong.service.set_tls_verify(on) + +Sets whether TLS verification is enabled while handshaking with the Service. + + The `on` argument is a boolean flag, where `true` means upstream verification + is enabled and `false` disables it. + + This call affects only the current request. If the trusted certificate store is + not set already (via [proxy_ssl_trusted_certificate](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_trusted_certificate) + or [kong.service.set_upstream_ssl_trusted_store](#kongserviceset_upstream_ssl_trusted_store)), + then TLS verification will always fail with "unable to get local issuer certificate" error. + + +**Phases** + +* `rewrite`, `access`, `balancer` + +**Parameters** + +* **on** (boolean): Whether to enable TLS certificate verification for the current request + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one + + +**Usage** + +``` lua +local ok, err = kong.service.set_tls_verify(true) +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservice) + + +### kong.service.set_tls_verify_depth(depth) + +Sets the maximum depth of verification when validating upstream server's TLS certificate. + + This call affects only the current request. For the depth to be actually used the verification + has to be enabled with either the [proxy_ssl_verify](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_verify) + directive or using the [kong.service.set_tls_verify](#kongserviceset_tls_verify) function. + + +**Phases** + +* `rewrite`, `access`, `balancer` + +**Parameters** + +* **depth** (number): Depth to use when validating. Must be non-negative + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one + + +**Usage** + +``` lua +local ok, err = kong.service.set_tls_verify_depth(3) +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservice) + + +### kong.service.set_tls_verify_store(store) + +Sets the CA trust store to use when validating upstream server's TLS certificate. + + This call affects only the current request. For the store to be actually used the verification + has to be enabled with either the [proxy_ssl_verify](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_verify) + directive or using the [kong.service.set_tls_verify](#kongserviceset_tls_verify) function. + + The resty.openssl.x509.store object can be created by following + [examples](https://github.com/Kong/lua-kong-nginx-module#restykongtlsset_upstream_ssl_trusted_store) from the Kong/lua-kong-nginx-module repo. + + +**Phases** + +* `rewrite`, `access`, `balancer` + +**Parameters** + +* **store** (table): resty.openssl.x509.store object to use + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one + + +**Usage** + +``` lua +local store = require("resty.openssl.x509.store") +local st = assert(store.new()) +-- st:add(...certificate) + +local ok, err = kong.service.set_tls_verify_store(st) +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservice) diff --git a/app/gateway/2.6.x/pdk/kong.service.request.md b/app/gateway/2.6.x/pdk/kong.service.request.md new file mode 100644 index 000000000000..2790c1da792f --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.service.request.md @@ -0,0 +1,505 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.service.request +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## kong.service.request + +Manipulation of the request to the Service + + + +### kong.service.request.enable_buffering() + +Enables buffered proxying that allows plugins to access service body and + response headers at the same time + +**Phases** + +* `rewrite`, `access` + +**Returns** + +* Nothing + + +**Usage** + +``` lua +kong.service.request.enable_buffering() +``` + +[Back to top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### kong.service.request.set_path(path) + +Sets the path component for the request to the service. + + The input accepts any valid *normalized* URI (including UTF-8 characters) + and this API will perform necessary escaping according to the RFC + to make the request valid. + + Input should **not** include the querystring. + +**Phases** + +* `access` + +**Parameters** + +* **path** (string): The path string. Special characters and UTF-8 characters are allowed. Example: "/v2/movies" or "/foo/😀" + +**Returns** + +* Nothing; throws an error on invalid inputs. + + +**Usage** + +``` lua +kong.service.request.set_path("/v2/movies") +``` + +[Back to top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### kong.service.request.set_method(method) + +Sets the HTTP method for the request to the service. + +**Phases** + +* `rewrite`, `access` + +**Parameters** + +* **method** (string): 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### 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 occurrences 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### kong.service.request.disable_tls() + +Disables the TLS handshake to upstream for [ngx\_stream\_proxy\_module](https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html). + Effectively this overrides [proxy\_ssl](https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_ssl) directive to `off` setting + for the current stream session. + + Note that once this function has been called it is not possible to re-enable TLS handshake for the current session. + + +**Phases** + +* `preread`, `balancer` + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one. + + +**Usage** + +``` lua +local ok, err = kong.service.request.disable_tls() +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservicerequest) diff --git a/app/gateway/2.6.x/pdk/kong.service.response.md b/app/gateway/2.6.x/pdk/kong.service.response.md new file mode 100644 index 000000000000..cc83cf4f4942 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.service.response.md @@ -0,0 +1,196 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.service.response +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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 top](#kongserviceresponse) + + +### 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 top](#kongserviceresponse) + + +### 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 top](#kongserviceresponse) + + +### kong.service.response.get_raw_body() + +Returns the raw buffered body. + +**Phases** + +* `header_filter`, `body_filter`, `log` + +**Returns** + +* `string` body The raw buffered body + + +**Usage** + +``` lua +-- Plugin needs to call kong.service.request.enable_buffering() on `rewrite` +-- or `access` phase prior calling this function. + +local body = kong.service.response.get_raw_body() +``` + +[Back to top](#kongserviceresponse) + + +### kong.service.response.get_body(mimetype[, mimetype[, max_args]]) + +Returns the decoded buffered body. + +**Phases** + +* `header_filter`, `body_filter`, `log` + +**Parameters** + +* **mimetype** (string, _optional_): the MIME type +* **mimetype** (string, _optional_): the MIME type +* **max_args** (number, _optional_): set a limit on the maximum number of parsed + +**Returns** + +* `string` body The raw buffered body + + +**Usage** + +``` lua +-- Plugin needs to call kong.service.request.enable_buffering() on `rewrite` +-- or `access` phase prior calling this function. + +local body = kong.service.response.get_body() +``` + +[Back to top](#kongserviceresponse) diff --git a/app/gateway/2.6.x/pdk/kong.table.md b/app/gateway/2.6.x/pdk/kong.table.md new file mode 100644 index 000000000000..360ddcb22ba0 --- /dev/null +++ b/app/gateway/2.6.x/pdk/kong.table.md @@ -0,0 +1,103 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.table +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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 top](#kongtable) + + +### 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 top](#kongtable) + + +### kong.table.merge([t1[, t2]]) + +Merges the contents of two tables together, producing a new one. + The entries of both tables are copied non-recursively to the new one. + If both tables have the same key, the second one takes precedence. + If only one table is given, it returns a copy. + +**Parameters** + +* **t1** (table, _optional_): The first table +* **t2** (table, _optional_): The second table + +**Returns** + +* `table` The (new) merged table + + +**Usage** + +``` lua +local t1 = {1, 2, 3, foo = "f"} +local t2 = {4, 5, bar = "b"} +local t3 = kong.table.merge(t1, t2) -- {4, 5, 3, foo = "f", bar = "b"} +``` + +[Back to top](#kongtable) diff --git a/app/gateway/2.6.x/plan-and-deploy/default-ports.md b/app/gateway/2.6.x/plan-and-deploy/default-ports.md new file mode 100644 index 000000000000..c9c8f5959efe --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/default-ports.md @@ -0,0 +1,23 @@ +--- +title: Default Ports +--- +By default, {{site.base_gateway}} listens on the following ports: + +| Port | Protocol | Description | Gateway tier | +|:-----------------------------------------------------------------------------------|:---------|:------------|:----------------------| +| [`:8000`](/gateway/{{page.release}}/reference/configuration/#proxy_listen) | HTTP | Takes incoming HTTP traffic from **Consumers**, and forwards it to upstream **Services**. | All tiers and modes | +| [`:8443`](/gateway/{{page.release}}/reference/configuration/#proxy_listen) | HTTPS | Takes incoming HTTPS traffic from **Consumers**, and forwards it to upstream **Services**. | All tiers and modes | +| [`:8001`](/gateway/{{page.release}}/reference/configuration/#admin_api_uri) | HTTP | Admin API. Listens for calls from the command line over HTTP. | All tiers and modes | +| [`:8444`](/gateway/{{page.release}}/reference/configuration/#admin_api_uri) | HTTPS | Admin API. Listens for calls from the command line over HTTPS. | All tiers and modes | +| [`:8005`](/gateway/{{page.release}}/plan-and-deploy/hybrid-mode/hybrid-mode-setup/) | HTTP | Hybrid mode only. Control Plane listens for traffic from Data Planes. | All tiers and modes | +| [`:8006`](/gateway/{{page.release}}/plan-and-deploy/hybrid-mode/hybrid-mode-setup/) | HTTP | Hybrid mode only. Control Plane listens for Vitals telemetry data from Data Planes. | {{site.ee_product_name}} tier | +| [`:8002`](/gateway/{{page.release}}/reference/configuration/#admin_gui_listen) | HTTP | Kong Manager (GUI). Listens for HTTP traffic. | {{site.base_gateway}} free mode | +| [`:8445`](/gateway/{{page.release}}/reference/configuration/#admin_gui_listen) | HTTPS | Kong Manager (GUI). Listens for HTTPS traffic. | {{site.base_gateway}} free mode | +| [`:8003`](/gateway/{{page.release}}/reference/configuration/#portal_gui_listen) | HTTP | Dev Portal. Listens for HTTP traffic, assuming Dev Portal is **enabled**. | {{site.ee_product_name}} tier | +| [`:8446`](/gateway/{{page.release}}/reference/configuration/#portal_gui_listen) | HTTPS | Dev Portal. Listens for HTTPS traffic, assuming Dev Portal is **enabled**. | {{site.ee_product_name}} tier | +| [`:8004`](/gateway/{{page.release}}/reference/configuration/#portal_api_listen) | HTTP | Dev Portal `/files` traffic over HTTP, assuming the Dev Portal is **enabled**. | {{site.ee_product_name}} tier | +| [`:8447`](/gateway/{{page.release}}/reference/configuration/#portal_api_listen) | HTTPS | Dev Portal `/files` traffic over HTTPS, assuming the Dev Portal is **enabled**. | {{site.ee_product_name}} tier | + +{:.note} +> **Note:** {{site.base_gateway}} free mode and Enterprise tier are not available for +open-source Gateway packages. diff --git a/app/gateway/2.6.x/plan-and-deploy/dns-considerations.md b/app/gateway/2.6.x/plan-and-deploy/dns-considerations.md new file mode 100644 index 000000000000..b4f1607037eb --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/dns-considerations.md @@ -0,0 +1,257 @@ +--- +title: DNS Considerations for Kong Gateway +badge: enterprise +--- + +{{site.base_gateway}} provides web applications that must be able to interact with +other Kong services to function properly: Kong Manager must be able to +interact with the Admin API, and the Dev Portal must be able to interact with +the Portal API. These applications are subject to security restrictions +enforced by browsers, and Kong must send appropriate information to browsers in +order for them to function properly. + +These security restrictions use the applications' DNS hostnames to evaluate +whether the applications' metadata satisfies the security constraints. As such, +you must design your DNS structure to meet the requirements. + +## Quick guide + +It is recommended you read through this document to understand why these +requirements exist and how they function. In brief, your environment must meet +one of the two criteria below: + +* Kong Manager and the Admin API are served from the same hostname, typically + by placing the Admin API under an otherwise unused path, such as `/_adminapi/`. +* Kong Manager and the Admin API are served from different hostnames with a + shared suffix (e.g. `kong.example` for `api.admin.kong.example` and + `manager.admin.kong.example`). Admin session configuration sets + `cookie_domain` to the shared suffix. + +The same applies to the Portal API and Dev Portal. + +The first option simplifies configuration in `kong.conf`, but requires an HTTP +proxy in front of the applications (because it uses HTTP path-based routing). +The Kong proxy can be used for this. The second option requires more +configuration in kong.conf, but can be used without proxying the applications. + +## CORS + +### Understanding CORS + +[Cross-Origin Resource Sharing, or CORS][mdn-cors], is a set of rules for web +applications that make requests across origins, i.e. to URLs that do not share +the same scheme, hostname, and port as the page making the request. When making +a cross-origin request, browsers send an `Origin` request header, and servers +must respond with a matching `Access-Control-Allow-Origin` (ACAO) header. If +the two headers do not match, the browser will discard the response, and any +application components that require that response's data will not function +properly. + +For example, the following request/response pairs have matching CORS headers, +and will succeed: + +``` +GET / HTTP/1.1 +Host: example.com +Origin: http://example.net + +HTTP/1.1 200 OK +Access-Control-Allow-Origin: http://example.net +``` + +``` +GET / HTTP/1.1 +Host: example.com +Origin: http://example.net + +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +``` + +`*` indicates that any origin is allowed. + +These requests do not have a matching pair of CORS headers, and will fail: + +``` +GET / HTTP/1.1 +Host: example.com +Origin: http://example.net + +HTTP/1.1 200 OK +Access-Control-Allow-Origin: http://badbadcors.example +``` + +``` +GET / HTTP/1.1 +Host: example.com +Origin: http://example.net + +HTTP/1.1 200 OK +``` + +Missing CORS headers when CORS headers are expected results in failure. + +### CORS in the context of {{site.base_gateway}} + +Kong Manager and the Dev Portal operate by issuing requests to their respective +APIs using JavaScript. These requests may be cross-origin depending on your +environment. + +Kong's services determine what CORS headers to send based on various location +hint settings in `kong.conf`. The Admin API obtains its ACAO header value from +`admin_gui_url` and the Portal API obtains its header value from the +information in the `portal_gui_protocol`, `portal_gui_host`, and +`portal_gui_use_subdomains` settings. You may optionally specify additional +Portal API origins using `portal_cors_origins`. + +You can configure your environment such that these requests are not +cross-origin by accessing both the GUI and its associated API via the same +hostname, e.g. by accessing Kong Manager at `https://admin.kong.example/` and +the Admin API at `https://admin.kong.example/_api/`. This option requires +placing a proxy in front of both Kong Manager and the Admin API to handle +path-based routing; you can use Kong's proxy for this purpose. Note that the +GUIs must be served at the root of their domains; you cannot place the APIs at +the root and the GUI under a path. + +### Troubleshooting + +CORS errors are shown in the browser developer console (for example, see documentation for +[Firefox][firefox-dev-console] and [Chrome][chrome-dev-console]) with +explanations of the specific issue. ACAO/Origin mismatches are most common, but +other error conditions can appear as well. + +For example, if you have mistyped your `admin_api_uri`, you will see something +like the following: + +``` +Access to XMLHttpRequest at 'https://admin.kong.example' from origin 'https://manager.kong.example' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://typo.kong.example' that is not equal to the supplied origin. +``` + +These errors are generally self-explanatory, but if the issue is not clear, +check the Network developer tool, find the requests for the path in the error, +and compare its `Origin` request header and `Access-Control-Allow-Origin` +response header (it may be missing entirely). + +## Cookies + +### Understanding cookies + +[Cookies][mdn-cookies] are small pieces of data saved by browsers for use in +future requests. Servers include a [Set-Cookie header][mdn-set-cookie] in their +response headers to set cookies, and browsers include a [Cookie +header][mdn-cookie] when making subsequent requests. + +Cookies are used for a variety of purposes and offer many settings to tailor +when a browser will include them to fit a particular use case. Of particular +interest are the following directives: + +- Cookie scope, defined by the cookie's `Domain` and `Path` directives. Absent + these, cookies are sent only to the hostname that created them: a cookie + created by `example.com` will not be sent with a request to + `www.example.com`. When `Domain` is specified, cookies are sent to that + hostname and its subdomains, so a cookie from `example.com` with + `Domain=example.com` *will* be sent with requests to `www.example.com`. +- The `Secure` directive, which determines whether a cookie can be sent over an + unencrypted (HTTP rather than HTTPS) connection. A cookie with `Secure` + cannot be sent over HTTP, and must be set using HTTPS. +- The `SameSite` directive, which controls when a cookie can be sent with + cross-origin requests. Note that cookies have a different notion of + cross-origin than CORS and check against the domain suffix: while + `example.com` sending a request to `api.example.com` is cross-origin for the + purposes of CORS, a cookie with `Domain=example.com` is considered same-site + for requests to `api.example.com`. `SameSite=Strict` cookies are only sent + with same-site requests, `Lax` are sent when navigating to a link from + another site, and `None` are sent with all cross-origin requests. + +### Cookies in the context of {{site.base_gateway}} + +After you log in to Kong Manager or the Dev Portal, Kong stores session +information in a cookie to recognize your browser during future requests. These +cookies are created using the [session plugin][session-plugin] (via +`admin_gui_session_conf`) or [OpenID Connect plugin][oidc-plugin]. +Configuration is more or less the same between each--the OpenID Connect plugin +contains an embedded version of the session plugin, so while cookie handling +code is the same, it is configured directly in the OpenID Connect plugin +settings (`admin_gui_auth_conf`). + +- `cookie_name` does not affect where the cookie is used, but should be set to + a unique value to avoid collisions: some configurations may use the same + `cookie_domain` for both admin and Portal cookies, and using the same name + for both would then cause their cookies to collide and overwrite one another. +- `cookie_domain` should match the common hostname suffix shared by the GUI and + its API. For example, if you use `api.admin.kong.example` and + `manager.admin.kong.example` for the Admin API and Kong Manager, + `cookie_domain` should be `admin.kong.example`. +- `cookie_samesite` should typically be left at its default, `strict`. `none` + is not necessary if you have your DNS records and `cookie_domain` set + following the examples in this document. `off` is only needed if the GUI and + API are on entirely separate hostnames, e.g. `admin.kong.example` for the API + and `manager.example.com` for Kong Manager. This configuration is not + recommended because `off` opens a vector for cross-site request forgery + attacks. It may be needed in some development or testing environments, but + should not be used in production. +- `cookie_secure` controls whether cookies can be sent over unsecured + (plaintext HTTP) requests. By default, it is set to `true`, which does not + permit sending the cookie over unsecured connections. This setting should + also remain on the default, but may be disabled in some development or + testing environments where HTTPS is not used. + +OpenID Connect uses the same settings, but prefixed with `session_`, e.g. +`session_cookie_name` rather than `cookie_name`. + +Dev Portal configuration does not differ significantly from Kong Manager +configuration, but is configured per workspace under the Portal > Settings +section of Kong Manager, in the "Session Config (JSON)" field. + +As with CORS, the above is not necessary if both the GUI and API use the same +hostname, with both behind a proxy and the API under a specific path on the +hostname. + +### Troubleshooting + +Issues with session cookies broadly fall into cases where the cookie is not +sent and cases where the cookie is not set. The network (for example, see documentation for +[Firefox][firefox-dev-network] or [Chrome][chrome-dev-network]) and +application/storage (see documentation for [Firefox][firefox-dev-storage] or +[Chrome][chrome-dev-application]) developer tools can assist with investigating +these. + +In the network tool, selecting individual requests will show their request and +response headers. Successful authentication requests should see a `Set-Cookie` +response header including a cookie whose name matches `cookie_name` setting, +and subsequent requests should include the same cookie in the `Cookie` request +header. + +If `Set-Cookie` is not present, it may be being stripped by some intermediate +proxy, or may indicate that the authentication handler encountered an error. +There should typically be other evidence in the response status and body in the +event of an error, and possible additional information in Kong's error logs. + +If the cookie is set but not sent, it may have been deleted or may not match +requests that need it. The application/storage tool will show current cookies +and their parameters. Review these to see if your requests do not meet the +criteria to send the cookie (e.g. the cookie domain is not a suffix for a +request that requires the cookie, or is not present) and adjust your session +configuration accordingly. + +If cookies are *not* present in application/storage, but were previously set +with `Set-Cookie`, they may have since been deleted, or may have expired. +Review the `Set-Cookie` information to see when the cookie was set to expire +and subsequent requests to determine if any other response has issued a +`Set-Cookie` that deleted it (by setting expiration to a date in the past). + +This troubleshooting information may not immediately indicate the cause of the issue, but can +help Kong Support pinpoint the cause. Please provide it in tickets if possible. + +[chrome-dev-application]: https://developers.google.com/web/tools/chrome-devtools#application +[chrome-dev-console]: https://developers.google.com/web/tools/chrome-devtools/console/log +[chrome-dev-network]: https://developers.google.com/web/tools/chrome-devtools#network +[firefox-dev-console]: https://developer.mozilla.org/en-US/docs/Tools/Web_Console/Opening_the_Web_Console +[firefox-dev-network]: https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor +[firefox-dev-storage]: https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector +[mdn-cookie]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cookie +[mdn-cookies]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies +[mdn-set-cookie]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie +[mdn-cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS +[oidc-plugin]: /hub/kong-inc/openid-connect/ +[session-plugin]: /hub/kong-inc/session/ diff --git a/app/gateway/2.6.x/plan-and-deploy/hybrid-mode/hybrid-mode-setup.md b/app/gateway/2.6.x/plan-and-deploy/hybrid-mode/hybrid-mode-setup.md new file mode 100644 index 000000000000..e9cd34edabc8 --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/hybrid-mode/hybrid-mode-setup.md @@ -0,0 +1,671 @@ +--- +title: Deploy Kong Gateway in Hybrid Mode +--- + +## Prerequisites + +To get started with a Hybrid mode deployment, first install an instance of +{{site.base_gateway}} with TLS to be your Control Plane (CP) node. See the +[installation documentation](/gateway/{{page.release}}/install-and-run/) +for details. + +We will bring up any subsequent Data Plane (DP) instances in this topic. + +{:.note} +> **Note:** For a Hybrid mode deployment on Kubernetes, see [Hybrid mode](https://github.com/Kong/charts/blob/main/charts/kong/README.md#hybrid-mode) +in the `kong/charts` repository. + +## Generate a certificate/key pair + +In Hybrid mode, a mutual TLS handshake (mTLS) is used for authentication so the +actual private key is never transferred on the network, and communication +between CP and DP nodes is secure. + +Before using Hybrid mode, you need a certificate/key pair. +{{site.base_gateway}} provides two modes for handling certificate/key pairs: + +* **Shared mode:** (Default) Use the Kong CLI to generate a certificate/key +pair, then distribute copies across nodes. The certificate/key pair is shared +by both CP and DP nodes. +* **PKI mode:** Provide certificates signed by a central certificate authority +(CA). Kong validates both sides by checking if they are from the same CA. This +eliminates the risks associated with transporting private keys. + +{:.warning} +> **Warning:** If you have a TLS-aware proxy between the DP and CP nodes, you +must use PKI mode and set `cluster_server_name` to the CP hostname in +`kong.conf`. Do not use shared mode, as it uses a non-standard value for TLS server name +indication, and this will confuse TLS-aware proxies that rely on SNI to route +traffic. + +For a breakdown of the properties used by these modes, see the +[configuration reference](#configuration-reference). + +{% navtabs %} +{% navtab Shared mode %} +{:.warning} + > **Warning:** Protect the Private Key. Ensure the private key file can only be accessed by + Kong nodes belonging to the cluster. If the key is compromised, you must + regenerate and replace certificates and keys on all CP and DP nodes. + +1. On an existing {{site.base_gateway}} instance, create a certificate/key pair: + ```bash + kong hybrid gen_cert + ``` + This will generate `cluster.crt` and `cluster.key` files and save them to + the current directory. By default, the certificate/key pair is valid for three + years, but can be adjusted with the `--days` option. See `kong hybrid --help` + for more usage information. + +2. Copy the `cluster.crt` and `cluster.key` files to the same directory +on all Kong CP and DP nodes; e.g., `/cluster/cluster`. + Set appropriate permissions on the key file so it can only be read by Kong. + +{% endnavtab %} +{% navtab PKI mode %} + +With PKI mode, the Hybrid cluster can use certificates signed by a central +certificate authority (CA). + +In this mode, the Control Plane and Data Plane don't need to use the same +`cluster_cert` and `cluster_cert_key`. Instead, Kong validates both sides by +checking if they are from the same CA. + +Prepare your CA certificates on the hosts where Kong will be running. + +{% navtabs %} +{% navtab CA Certificate Example %} +Typically, a CA certificate will look like this: + +``` +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 5d:29:73:bf:c3:da:5f:60:69:da:73:ed:0e:2e:97:6f:7f:4c:db:4b + Signature Algorithm: ecdsa-with-SHA256 + Issuer: O = Kong Inc., CN = Hybrid Root CA + Validity + Not Before: Jul 7 12:36:10 2020 GMT + Not After : Jul 7 12:36:40 2023 GMT + Subject: O = Kong Inc., CN = Hybrid Root CA + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:df:49:9f:39:e6:2c:52:9f:46:7a:df:ae:7b:9b: + 87:1e:76:bb:2e:1d:9c:61:77:07:e5:8a:ba:34:53: + 3a:27:4c:1e:76:23:b4:a2:08:80:b4:1f:18:7a:0b: + 79:de:ea:8c:23:94:e6:2f:57:cf:27:b4:0a:52:59: + 90:2c:2b:86:03 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 8A:0F:07:61:1A:0F:F4:B4:5D:B7:F3:B7:28:D1:C5:4B:81:A2:B9:25 + X509v3 Authority Key Identifier: + keyid:8A:0F:07:61:1A:0F:F4:B4:5D:B7:F3:B7:28:D1:C5:4B:81:A2:B9:25 + + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:20:68:3c:d1:f3:63:a2:aa:b4:59:c9:52:af:33:b7: + 3f:ca:3a:2b:1c:9d:87:0c:c0:47:ff:a2:c4:af:3e:b0:36:29: + 02:21:00:86:ce:d0:fc:ba:92:e9:59:16:1c:c3:b2:11:11:ed: + 01:5d:16:49:d0:f9:0c:1d:35:0d:40:ba:19:98:31:76:57 +``` +{% endnavtab %} + +{% navtab CA Certificate on CP %} +Here is an example of a CA certificate on a Control Plane: + +``` +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 18:cc:a3:6b:aa:77:0a:69:c6:d5:ff:12:be:be:c0:ac:5c:ff:f1:1e + Signature Algorithm: ecdsa-with-SHA256 + Issuer: CN = Hybrid Intermediate CA + Validity + Not Before: Jul 31 00:59:29 2020 GMT + Not After : Oct 29 00:59:59 2020 GMT + Subject: CN = control-plane.kong.yourcorp.tld + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:f8:3a:a9:d2:e2:79:19:19:f3:1c:58:a0:23:60: + 78:04:1f:7e:e2:bb:60:d2:29:50:ad:7c:9b:8e:22: + 1c:54:c2:ce:68:b8:6c:8a:f6:92:9d:0c:ce:08:d3: + aa:0c:20:67:41:32:18:63:c9:dd:50:31:60:d6:8b: + 8d:f9:7b:b5:37 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Server Authentication + X509v3 Subject Key Identifier: + 70:C7:F0:3B:CD:EB:8D:1B:FF:6A:7C:E0:A4:F0:C6:4C:4A:19:B8:7F + X509v3 Authority Key Identifier: + keyid:16:0D:CF:92:3B:31:B0:61:E5:AB:EE:91:42:B9:60:56:0A:88:92:82 + + X509v3 Subject Alternative Name: + DNS:control-plane.kong.yourcorp.tld, DNS:alternate-control-plane.kong.yourcorp.tld + X509v3 CRL Distribution Points: + + Full Name: + URI:https://crl-service.yourcorp.tld/v1/pki/crl + + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:5d:dd:ec:a8:4f:e7:5b:7d:2f:3f:ec:b5:40:d7: + de:5e:96:e1:db:b7:73:d6:84:2e:be:89:93:77:f1:05:07:f3: + 02:20:16:56:d9:90:06:cf:98:07:87:33:dc:ef:f4:cc:6b:d1: + 19:8f:64:ee:82:a6:e8:e6:de:57:a7:24:82:72:82:49 +``` +{% endnavtab %} + +{% navtab CA Certificate on DP %} +Here is an example of a CA certificate on a Data Plane: + +``` +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 4d:8b:eb:89:a2:ed:b5:29:80:94:31:e4:94:86:ce:4f:98:5a:ad:a0 + Signature Algorithm: ecdsa-with-SHA256 + Issuer: CN = Hybrid Intermediate CA + Validity + Not Before: Jul 31 00:57:01 2020 GMT + Not After : Oct 29 00:57:31 2020 GMT + Subject: CN = kong-dp-ce39edecp.service + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:19:51:80:4c:6d:8c:a8:05:63:42:71:a2:9a:23: + 34:34:92:c6:2a:d3:e5:15:6e:36:44:85:64:0a:4c: + 12:16:82:3f:b7:4c:e1:a1:5a:49:5d:4c:5e:af:3c: + c1:37:e7:91:e2:b5:52:41:a0:51:ac:13:7b:cc:69: + 93:82:9b:2f:e2 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Client Authentication + X509v3 Subject Key Identifier: + 25:82:8C:93:85:35:C3:D6:34:CF:CB:7B:D6:14:97:46:84:B9:2B:87 + X509v3 Authority Key Identifier: + keyid:16:0D:CF:92:3B:31:B0:61:E5:AB:EE:91:42:B9:60:56:0A:88:92:82 + X509v3 CRL Distribution Points: + + Full Name: + URI:https://crl-service.yourcorp.tld/v1/pki/crl + + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:65:2f:5e:30:f7:a4:28:14:88:53:58:c5:85:24: + 35:50:25:c9:fe:db:2f:72:9f:ad:7d:a0:67:67:36:32:2b:d2: + 02:20:2a:27:7d:eb:75:a6:ee:65:8b:f1:66:a4:99:32:56:7c: + ad:ca:3a:d5:50:8f:cf:aa:6d:c2:1c:af:a4:ca:75:e8 +``` +{% endnavtab %} +{% endnavtabs %} + +> **Note:** Certificates on CP and DP must contain the `TLS Web Server Authentication` and +`TLS Web Client Authentication` as X509v3 Extended Key Usage extension, respectively. + +Kong doesn't validate the CommonName (CN) in the DP certificate; it can take an arbitrary value. + +{% endnavtab %} +{% endnavtabs %} + +## Set up the control plane +Next, give the Control Plane node the `control_plane` role, and set +certificate/key parameters to point at the location of your certificates and +keys. + +{% navtabs %} +{% navtab Using Docker %} + +1. In your Docker container, set the following environment variables: + + For `shared` certificate mode, use: + ```bash + KONG_ROLE=control_plane + KONG_CLUSTER_CERT=//cluster.crt + KONG_CLUSTER_CERT_KEY=//cluster.key + ``` + + For `pki` certificate mode, use: + ```bash + KONG_ROLE=control_plane + KONG_CLUSTER_MTLS=pki + KONG_CLUSTER_CA_CERT=//ca-cert.pem + KONG_CLUSTER_CERT=//control-plane.crt + KONG_CLUSTER_CERT_KEY=//control-plane.key + ``` + By setting the role of the node to `control_plane`, this node will listen on + port `0.0.0.0:8005` by default for Data Plane connections, and on port + `0.0.0.0:8006` for telemetry data. These ports on the + Control Plane will need to be accessible by all Data Planes it controls through + any firewalls you may have in place. + + For PKI mode, `KONG_CLUSTER_CA_CERT` specifies the root CA certificate for + `KONG_CLUSTER_CERT` and `KONG_CLUSTER_CERT_KEY`. This certificate must be + the root CA certificate and not any of an intermediate CA. Kong allows a + maximum of three levels of intermediate CAs to be used between the root CA + and the cluster certificate. + + If you need to change the ports that the Control Plane listens on, set: + ```bash + KONG_CLUSTER_LISTEN=0.0.0.0: + KONG_CLUSTER_TELEMETRY_LISTEN=0.0.0.0: + ``` + +2. Next, start Kong, or reload Kong if it's already running: + ```bash + kong start + ``` + ```bash + kong reload + ``` + +{% endnavtab %} +{% navtab Using kong.conf %} +1. In `kong.conf`, set the following configuration parameters: + + For `shared` certificate mode, use: + ```bash + role = control_plane + cluster_cert = //cluster.crt + cluster_cert_key = //cluster.key + ``` + + For `pki` certificate mode, use: + ```bash + role = control_plane + cluster_mtls = pki + cluster_ca_cert = //ca-cert.pem + cluster_cert = //control-plane.crt + cluster_cert_key = //control-plane.key + ``` + + By setting the role of the node to `control_plane`, this node will listen on + port `0.0.0.0:8005` by default for Data Plane connections, and on port + `0.0.0.0:8006` for telemetry data. These ports on the + Control Plane will need to be accessible by all Data Planes it controls through + any firewalls you may have in place. + + For PKI mode, `cluster_ca_cert` specifies the root CA certificate for + `cluster_cert` and `cluster_cert_key`. This certificate must be the root CA + certificate and not any of an intermediate CA. Kong allows a maximum of three + levels of intermediate CAs to be used between the root CA and the cluster + certificate. + + If you need to change the ports that the Control Plane listens on, set: + ```bash + cluster_listen=0.0.0.0: + cluster_telemetry_listen=0.0.0.0: + ``` + +2. Restart Kong for the settings to take effect: + ```bash + kong restart + ``` +{% endnavtab %} +{% endnavtabs %} + +Note that the Control Plane still needs a database (PostgreSQL or Cassandra) to +store the central configurations, although the database never needs to +be accessed by Data Plane nodes. You may run multiple Control Plane nodes to +provide load balancing and redundancy, as long as they all point to the same +backend database. + +{:.note} +> **Note:** Control Plane nodes cannot be used for proxying. + +### (Optional) Revocation checks of Data Plane certificates + +When Kong is running Hybrid mode with PKI mode, the Control Plane can be configured to +optionally check for revocation status of the connecting Data Plane certificate. + +The supported method is through Online Certificate Status Protocol (OCSP) responders. +Issued data plane certificates must contain the Certificate Authority Information Access extension +that references the URI of OCSP responder that can be reached from the Control Plane. + +To enable OCSP checks, set the `cluster_ocsp` config on the Control Plane to one of the following values: + +* `on`: OCSP revocation check is enabled and the Data Plane must pass the revocation check +to establish connection with the Control Plane. This implies that certificates without the +OCSP extension or unreachable OCSP responder also prevents a connection from being established. +* `off`: OCSP revocation check is disabled (default). +* `optional`: OCSP revocation check will be attempted, however, if the OCSP responder URI is not +found inside the Data Plane-provided certificate or communication with the OCSP responder failed, +then Data Plane is still allowed through. + +Note that OCSP checks are only performed on the Control Plane against certificates provided by incoming Data Plane +nodes. The `cluster_ocsp` config has no effect on Data Plane nodes. +`cluster_oscp` affects all Hybrid mode connections established from a Data Plane to its Control Plane. + +## Install and start data planes +Now that the Control Plane is running, you can attach Data Plane nodes to it to +start serving traffic. + +In this step, you will give all Data Plane nodes the `data_plane` role, +point them to the Control Plane, set certificate/key parameters to point at +the location of your certificates and keys, and ensure the database +is disabled. + +In addition, the certificate from `cluster_cert` (in `shared` mode) or `cluster_ca_cert` +(in `pki` mode) is automatically added to the trusted chain in +[`lua_ssl_trusted_certificate`](/gateway/{{page.release}}/reference/configuration/#lua_ssl_trusted_certificate). + +{:.important} +> **Important:** Data Plane nodes receive updates from the Control Plane via a format +similar to declarative config, therefore `database` has to be set to +`off` for Kong to start up properly. + +See the [DP node start sequence](#dp-node-start-sequence) for more information +on how data plane nodes process configuration. + + +{% navtabs %} +{% navtab Using Docker %} +1. Using the [Docker installation documentation](/gateway/{{page.release}}/install-and-run/docker/), +follow the instructions to: + 1. [Download {{site.base_gateway}}](/gateway/{{page.release}}/install-and-run/docker/). + 2. [Create a Docker network](/gateway/{{page.release}}/install-and-run/docker/#install-gateway-in-db-less-mode). + + {:.warning} + > **Warning:** Do not start or create a database on this node. + + +1. Bring up your Data Plane container with the following settings: + + For `shared` certificate mode, use: + +{% capture shared-mode-cp %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```bash +docker run -d --name kong-dp --network=kong-net \ +-e "KONG_ROLE=data_plane" \ +-e "KONG_DATABASE=off" \ +-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \ +-e "KONG_CLUSTER_CONTROL_PLANE=control-plane..com:8005" \ +-e "KONG_CLUSTER_TELEMETRY_ENDPOINT=control-plane..com:8006" \ +-e "KONG_CLUSTER_CERT=//cluster.crt" \ +-e "KONG_CLUSTER_CERT_KEY=//cluster.key" \ +--mount type=bind,source="$(pwd)"/cluster,target=,readonly \ +-p 8000:8000 \ +kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +docker run -d --name kong-dp --network=kong-net \ +-e "KONG_ROLE=data_plane" \ +-e "KONG_DATABASE=off" \ +-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \ +-e "KONG_CLUSTER_CONTROL_PLANE=control-plane..com:8005" \ +-e "KONG_CLUSTER_TELEMETRY_ENDPOINT=control-plane..com:8006" \ +-e "KONG_CLUSTER_CERT=//cluster.crt" \ +-e "KONG_CLUSTER_CERT_KEY=//cluster.key" \ +--mount type=bind,source="$(pwd)"/cluster,target=,readonly \ +-p 8000:8000 \ +kong:{{page.releases_hash[page.version-index].ce-version}}-alpine +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ shared-mode-cp | indent | replace: " ", "" }} + + For `pki` certificate mode, use: + +{% capture pki-mode-cp %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```bash +docker run -d --name kong-dp --network=kong-net \ +-e "KONG_ROLE=data_plane" \ +-e "KONG_DATABASE=off" \ +-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \ +-e "KONG_CLUSTER_CONTROL_PLANE=control-plane..com:8005" \ +-e "KONG_CLUSTER_TELEMETRY_ENDPOINT=control-plane..com:8006" \ +-e "KONG_CLUSTER_MTLS=pki" \ +-e "KONG_CLUSTER_SERVER_NAME=control-plane.kong.yourcorp.tld" \ +-e "KONG_CLUSTER_CERT=data-plane.crt" \ +-e "KONG_CLUSTER_CERT_KEY=//data-plane.crt" \ +-e "KONG_CLUSTER_CA_CERT=//ca-cert.pem" \ +--mount type=bind,source="$(pwd)"/cluster,target=,readonly \ +-p 8000:8000 \ +kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +docker run -d --name kong-dp --network=kong-net \ +-e "KONG_ROLE=data_plane" \ +-e "KONG_DATABASE=off" \ +-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \ +-e "KONG_CLUSTER_CONTROL_PLANE=control-plane..com:8005" \ +-e "KONG_CLUSTER_TELEMETRY_ENDPOINT=control-plane..com:8006" \ +-e "KONG_CLUSTER_MTLS=pki" \ +-e "KONG_CLUSTER_SERVER_NAME=control-plane.kong.yourcorp.tld" \ +-e "KONG_CLUSTER_CERT=data-plane.crt" \ +-e "KONG_CLUSTER_CERT_KEY=//data-plane.crt" \ +-e "KONG_CLUSTER_CA_CERT=//ca-cert.pem" \ +--mount type=bind,source="$(pwd)"/cluster,target=,readonly \ +-p 8000:8000 \ +kong:{{page.releases_hash[page.version-index].ce-version}}-alpine +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ pki-mode-cp | indent | replace: " ", "" }} + + Where: + + `--name` and `--network` + : The tag of the {{site.base_gateway}} image that you're using, and the Docker network it communicates on. + + `KONG_CLUSTER_CONTROL_PLANE` + : Sets the address and port of the Control Plane (port `8005` by default). + + `KONG_DATABASE` + : Specifies whether this node connects directly to a database. + + `` and `target=` + : Are the same path, pointing to the location of the `cluster.key` and + `cluster.crt` files. + + `KONG_CLUSTER_SERVER_NAME` + : Specifies the SNI (Server Name Indication + extension) to use for Data Plane connections to the Control Plane through + TLS. When not set, Data Plane will use `kong_clustering` as the SNI. + + : You can also optionally use `KONG_CLUSTER_TELEMETRY_SERVER_NAME` + to set a custom SNI for telemetry data. If not set, it defaults to + `KONG_CLUSTER_SERVER_NAME`. + + `KONG_CLUSTER_TELEMETRY_ENDPOINT` + : Optional setting, needed for telemetry gathering. Not available in open-source deployments. + +1. If needed, bring up any subsequent Data Planes using the same settings. + +{% endnavtab %} +{% navtab Using kong.conf %} + +1. Find the documentation for [your platform](/gateway/{{page.release}}/install-and-run/), +and follow the instructions in Steps 1 and 2 **only** to download +{{site.base_gateway}} and install Kong. + + {:.note} + > **Note:** for Docker, see the **Docker** tab above. For Kubernetes, see the + [Hybrid mode documentation](https://github.com/Kong/charts/blob/main/charts/kong/README.md#hybrid-mode) + in the `kong/charts` repository. + + {:.warning} + > Do not start or create a database on this node. + + +2. In `kong.conf`, set the following configuration parameters: + + For `shared` certificate mode, use: + ```bash + role = data_plane + database = off + proxy_listen = 0.0.0.0:8000 + cluster_control_plane = control-plane..com:8005 + cluster_telemetry_endpoint = control-plane..com:8006 + cluster_cert = //cluster.crt + cluster_cert_key = //cluster.key + ``` + + For `pki` certificate mode, use: + ```bash + role = data_plane + database = off + proxy_listen = 0.0.0.0:8000 + cluster_control_plane = control-plane..com:8005 + cluster_telemetry_endpoint = control-plane..com:8006 + cluster_mtls = pki + cluster_server_name = control-plane.kong.yourcorp.tld + cluster_cert = //data-plane.crt + cluster_cert_key = //data-plane.crt + cluster_ca_cert = //ca-cert.pem + ``` + + Where: + + `cluster_control_plane` + : Sets the address and port of the Control Plane (port `8005` by default). + + `database` + : Specifies whether this node connects directly to a database. + + `` + : Specifies the location of the `cluster.key` and `cluster.crt` files. + + `cluster_server_name` + : Specifies the SNI (Server Name Indication extension) + to use for Data Plane connections to the Control Plane through TLS. When + not set, Data Plane will use `kong_clustering` as the SNI. + + : You can also optionally use `cluster_telemetry_server_name` + to set a custom SNI for telemetry data. If not set, it defaults to + `cluster_server_name`. + + `cluster_telemetry_endpoint` + : Optional setting, needed for telemetry gathering. Not available in open-source deployments. + +3. Restart Kong for the settings to take effect: + ```bash + kong restart + ``` +{% endnavtab %} +{% endnavtabs %} + +## Verify that nodes are connected + +Use the Control Plane’s Cluster Status API to monitor your Data Planes. It +provides: +* The name of the node +* The last time the node synced with the Control Plane +* The version of the config currently running on each Data Plane + +To check whether the CP and DP nodes you just brought up are connected, run the +following on a Control Plane: +{% navtabs %} +{% navtab Using cURL %} +```bash +curl -i -X GET http://localhost:8001/clustering/data-planes +``` +{% endnavtab %} +{% navtab Using HTTPie %} +```bash +http :8001/clustering/data-planes +``` +{% endnavtab %} +{% endnavtabs %} +The output shows all of the connected Data Plane instances in the cluster: + +```json +{ + "data": [ + { + "config_hash": "a9a166c59873245db8f1a747ba9a80a7", + "hostname": "data-plane-2", + "id": "ed58ac85-dba6-4946-999d-e8b5071607d4", + "ip": "192.168.10.3", + "last_seen": 1580623199, + "status": "connected" + }, + { + "config_hash": "a9a166c59873245db8f1a747ba9a80a7", + "hostname": "data-plane-1", + "id": "ed58ac85-dba6-4946-999d-e8b5071607d4", + "ip": "192.168.10.4", + "last_seen": 1580623200, + "status": "connected" + } + ], + "next": null +} +``` + +## References + +### DP node start sequence + +When set as a DP node, {{site.base_gateway}} processes configuration in the +following order: + +1. **Config cache**: If the file `config.json.gz` exists in the `kong_prefix` +path (`/usr/local/kong` by default), the DP node loads it as configuration. +2. **`declarative_config` exists**: If there is no config cache and the +`declarative_config` parameter is set, the DP node loads the specified file. +3. **Empty config**: If there is no config cache or declarative +configuration file available, the node starts with empty configuration. In this +state, it returns 404 to all requests. +4. **Contact CP Node**: In all cases, the DP node contacts the CP node to retrieve +the latest configuration. If successful, it gets stored in the local config +cache (`config.json.gz`). + +### Configuration reference + +Use the following configuration properties to configure {{site.base_gateway}} +in Hybrid mode. + +Parameter | Description | CP or DP {:width=10%:} +--------- | ----------- | ---------------------- +[`role`](/gateway/{{page.release}}/reference/configuration/#role)
    *Required* | Determines whether the {{site.base_gateway}} instance is a Control Plane or a Data Plane. Valid values are `control_plane` or `data_plane`. | Both +[`cluster_listen`](/gateway/{{page.release}}/reference/configuration/#cluster_listen)
    *Optional*

    **Default:** `0.0.0.0:8005`| List of addresses and ports on which the Control Plane will listen for incoming Data Plane connections. This port is always protected with Mutual TLS (mTLS) encryption. Ignored on Data Plane nodes. | CP +[`proxy_listen`](/gateway/{{page.release}}/reference/configuration/#proxy_listen)
    *Required* | Comma-separated list of addresses and ports on which the proxy server should listen for HTTP/HTTPS traffic. Ignored on Control Plane nodes. | DP +[`cluster_telemetry_listen`](/gateway/{{page.release}}/reference/configuration/#cluster_telemetry_listen)
    *Optional*

    **Default:** `0.0.0.0:8006`| List of addresses and ports on which the Control Plane will listen for Data Plane telemetry data. This port is always protected with Mutual TLS (mTLS) encryption. Ignored on Data Plane nodes. | CP +[`cluster_telemetry_endpoint`](/gateway/{{page.release}}/reference/configuration/#cluster_telemetry_endpoint)
    *Required for Enterprise deployments* | The port that the Data Plane uses to send telemetry data to the Control Plane. Ignored on Control Plane nodes. | DP +[`cluster_control_plane`](/gateway/{{page.release}}/reference/configuration/#cluster_control_plane)
    *Required* | Address and port that the Data Plane nodes use to connect to the Control Plane. Must point to the port configured using the [`cluster_listen`](/gateway/{{page.release}}/reference/configuration/#cluster_listen) property on the Control Plane node. Ignored on Control Plane nodes. | DP +[`cluster_mtls`](/gateway/{{page.release}}/reference/configuration/#cluster_mtls)
    *Optional*

    **Default:** `"shared"` | One of `"shared"` or `"pki"`. Indicates whether Hybrid Mode will use a shared certificate/key pair for CP/DP mTLS or if PKI mode will be used. See below sections for differences in mTLS modes. | Both + +The following properties are used differently between `shared` and `pki` modes: + +Parameter | Description | Shared Mode {:width=12%:} | PKI Mode {:width=30%:} +--------- | ----------- | ------------------------- | ---------------------- +[`cluster_cert`](/gateway/{{page.release}}/reference/configuration/#cluster_cert) and [`cluster_cert_key`](/gateway/{{page.release}}/reference/configuration/#cluster_cert_key)
    *Required* | Certificate/key pair used for mTLS between CP/DP nodes. | Same between CP/DP nodes. | Unique certificate for each node, generated from the CA specified by `cluster_ca_cert`. +[`cluster_ca_cert`](/gateway/{{page.release}}/reference/configuration/#cluster_ca_cert)
    *Required in PKI mode* | The trusted CA certificate file in PEM format used to verify the `cluster_cert`. | *Ignored* | CA certificate used to verify `cluster_cert`, same between CP/DP nodes. *Required* +[`cluster_server_name`](/gateway/{{page.release}}/reference/configuration/#cluster_server_name)
    *Required in PKI mode* | The SNI presented by the DP node mTLS handshake. | *Ignored* | In PKI mode, the DP nodes will also verify that the Common Name (CN) or Subject Alternative Name (SAN) inside the certificate presented by CP matches the `cluster_server_name` value. +[`cluster_telemetry_server_name`](/gateway/{{page.release}}/reference/configuration/#cluster_telemetry_server_name) | The telemetry SNI presented by the DP node mTLS handshake. If not specified, falls back on SNI set in `cluster_server_name`. | *Ignored* | In PKI mode, the DP nodes will also verify that the Common Name (CN) or Subject Alternative Name (SAN) inside the certificate presented by CP matches the `cluster_telemetry_server_name` value. + +## Next steps + +Now, you can start managing the cluster using the Control Plane. Once +all instances are set up, use the Admin API on the Control Plane as usual, and +these changes will be synced and updated on the Data Plane nodes automatically +within seconds. diff --git a/app/gateway/2.6.x/plan-and-deploy/hybrid-mode/index.md b/app/gateway/2.6.x/plan-and-deploy/hybrid-mode/index.md new file mode 100644 index 000000000000..72c4076afec7 --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/hybrid-mode/index.md @@ -0,0 +1,230 @@ +--- +title: Hybrid Mode Overview +--- + +Traditionally, Kong has always required a database, which could be either +PostgreSQL or Cassandra, to store configured entities such as Routes, Services, +and Plugins. + +Starting with {{site.base_gateway}} 2.1, Kong can be deployed in +Hybrid mode, also known as Control Plane / Data Plane Separation (CP/DP). + +In this mode, Kong nodes in a cluster are split into two roles: Control Plane +(CP), where configuration is managed and the Admin API is served from; and Data +Plane (DP), which serves traffic for the proxy. Each DP node is connected to one +of the CP nodes. Instead of accessing the database contents directly in the +traditional deployment method, the DP nodes maintain connection with CP nodes, +and receive the latest configuration. + +![Hybrid mode topology](/assets/images/products/gateway/deployment-hybrid-2.png) + +When you create a new Data Plane node, it establishes a connection to the +Control Plane. The Control Plane listens on port 8005 for connections and +tracks any incoming data from its Data Planes. + +Once connected, every Admin API or Kong Manager action on the Control Plane +triggers an update to the Data Planes in the cluster. + +## Benefits + +Hybrid mode deployments have the following benefits: + +* **Deployment flexibility:** Users can deploy groups of Data Planes in +different data centers, geographies, or zones without needing a local clustered +database for each DP group. +* **Increased reliability:** The availability of the database does not affect +the availability of the Data Planes. Each DP caches the latest configuration it +received from the Control Plane on local disk storage, so if CP nodes are down, +the DP nodes keep functioning. + * While the CP is down, DP nodes constantly try to reestablish communication. + * DP nodes can be restarted while the CP is down, and still proxy traffic + normally. +* **Traffic reduction:** Drastically reduces the amount of traffic to and from +the database, since only CP nodes need a direct connection to the database. +* **Increased security:** If one of the DP nodes is compromised, an attacker +won’t be able to affect other nodes in the Kong cluster. +* **Ease of management:** Admins only need to interact with the CP nodes to +control and monitor the status of the entire Kong cluster. + +## Platform Compatibility + +You can run {{site.base_gateway}} in Hybrid mode on any platform where +{{site.base_gateway}} is [supported](/gateway/{{page.release}}/install-and-run/). + +### Kubernetes Support and Additional Documentation + +[{{site.base_gateway}} on Kubernetes](/gateway/{{page.release}}/install-and-run/kubernetes) +fully supports Hybrid mode deployments, with or without the {{site.kic_product_name}}. + +For the full Kubernetes Hybrid mode documentation, see +[Hybrid mode](https://github.com/Kong/charts/blob/main/charts/kong/README.md#hybrid-mode) +in the `kong/charts` repository. + +## Version Compatibility + +{{site.base_gateway}} control planes only allow connections from data planes with the +same major version. +Control planes won't allow connections from data planes with newer minor versions. + +For example, a {{site.base_gateway}} v2.5.2 control plane: + +- Accepts a {{site.base_gateway}} 2.5.0, 2.5.1 and 2.5.2 data plane. +- Accepts a {{site.base_gateway}} 2.3.8, 2.2.1 and 2.2.0 data plane. +- Accepts a {{site.base_gateway}} 2.5.3 data plane (newer patch version on the data plane is accepted). +- Rejects a {{site.base_gateway}} 1.0.0 data plane (major version differs). +- Rejects a {{site.base_gateway}} 2.6.0 data plane (minor version on data plane is newer). + +Furthermore, for every plugin that is configured on the {{site.base_gateway}} +control plane, new configs are only pushed to data planes that have those configured +plugins installed and loaded. The major version of those configured plugins must +be the same on both the control planes and data planes. Also, the minor versions +of the plugins on the data planes can not be newer than versions installed on the +control planes. Similar to {{site.base_gateway}} version checks, +plugin patch versions are also ignored when determining compatibility. + +{:.important} +> Configured plugins means any plugin that is either enabled globally or +configured by services, routes, or consumers. + +For example, if a {{site.base_gateway}} control plane has `plugin1` v1.1.1 +and `plugin2` v2.1.0 installed, and `plugin1` is configured by a `Route` object: + +- It accepts {{site.base_gateway}} data planes with `plugin1` v1.1.2, +`plugin2` not installed. +- It accepts {{site.base_gateway}} data planes with `plugin1` v1.1.2, +`plugin2` v2.1.0, and `plugin3` v9.8.1 installed. +- It accepts {{site.base_gateway}} data planes with `plugin1` v1.1.1 +and `plugin3` v9.8.1 installed. +- It rejects {{site.base_gateway}} data planes with `plugin1` v1.2.0, +`plugin2` v2.1.0 installed (minor version of plugin on data plane is newer). +- It rejects {{site.base_gateway}} data planes with `plugin1` not installed +(plugin configured on control plane but not installed on data plane). + +Version compatibility checks between the control plane and data plane +occur at configuration read time. As each data plane proxy receives +configuration updates, it checks to see if it can enable the requested +features. If the control plane has a newer version of {{site.base_gateway}} +than the data plane proxy, but the configuration doesn’t include any new features +from that newer version, the data plane proxy reads and applies it as expected. + +For instance, a new version of {{site.base_gateway}} includes a new +plugin offering, and you update your control plane with that version. You can +still send configurations to your data planes that are on a less recent version +as long as you have not added the new plugin offering to your configuration. +If you add the new plugin to your configuration, you will need to update your +data planes to the newer version for the data planes to continue to read from +the control plane. + +If the compatibility checks fail, the control plane stops +pushing out new config to the incompatible data planes to avoid breaking them. + +If a config can not be pushed to a data plane due to failure of the +compatibility checks, the control plane will contain `warn` level lines in the +`error.log` similar to the following: + +```bash +unable to send updated configuration to DP node with hostname: localhost.localdomain ip: 127.0.0.1 reason: version mismatches, CP version: 2.2 DP version: 2.1 +unable to send updated configuration to DP node with hostname: localhost.localdomain ip: 127.0.0.1 reason: CP and DP does not have same set of plugins installed or their versions might differ +``` + +In addition, the `/clustering/data-planes` Admin API endpoint returns +the version of the data plane node and the latest config hash the node is +using. This data helps detect version incompatibilities from the +control plane side. + +## Fault tolerance + +A valid question you may ask is: What would happen if control plane nodes are down, +will the data plane keep functioning? The answer is yes. Data plane caches +the latest configuration it received from the control plane on the local disk. +In case the control plane stops working, the data plane will keep serving requests using +cached configurations. It does so while constantly trying to reestablish communication +with the control plane. + +This means that the Data Plane nodes can be stopped even for extended periods +of time, and the Data Plane will still proxy traffic normally. Data Plane +nodes can be restarted while in disconnected mode, and will load the last +configuration in the cache to start working. When the Control Plane is brought +up again, the Data Plane nodes will contact them and resume connected mode. + +### Disconnected Mode + +The viability of the Data Plane while disconnected means that Control Plane +updates or database restores can be done with peace of mind. First bring down +the Control Plane, perform all required downtime processes, and only bring up +the Control Plane after verifying the success and correctness of the procedure. +During that time, the Data Plane will keep working with the latest configuration. + +A new Data Plane node can be provisioned during Control Plane downtime. This +requires either copying the config cache file (`config.json.gz`) from another +Data Plane node, or using a declarative configuration. In either case, if it +has the role of `"data_plane"`, it will also keep trying to contact the Control +Plane until it's up again. + +To change a disconnected Data Plane node's configuration, you have to remove +the config cache file (`config.json.gz`), ensure the `declarative_config` +parameter or the `KONG_DECLARATIVE_CONFIG` environment variable is set, and set +the whole configuration in the referenced YAML file. + +### License deployment + +If you have an Enterprise license, the license file must be +deployed to control plane nodes. The control planes then distribute the license +to the data planes in their clusters. + +Use the [`/licenses`](/gateway/{{page.release}}/admin-api/licenses/reference/) +endpoint to apply the license to the control plane. + +## Limitations + +### Configuration Inflexibility + +When a configuration change is made at the Control Plane level via the Admin +API, it immediately triggers a cluster-wide update of all Data Plane +configurations. This means that the same configuration is synced from the CP to +all DPs, and the update cannot be scheduled or batched. For different DPs to +have different configurations, they will need their own CP instances. + +### Plugin Incompatibility + +When plugins are running on a Data Plane in hybrid mode, there is no Admin API +exposed directly from that DP. Since the Admin API is only exposed from the +Control Plane, all plugin configuration has to occur from the CP. Due to this +setup, and the configuration sync format between the CP and the DP, some plugins +have limitations in Hybrid mode: + +* [**Key Auth Encrypted:**](/hub/kong-inc/key-auth-enc/) The time-to-live setting +(`ttl`), which determines the length of time a credential remains valid, does +not work in Hybrid mode. +* [**Rate Limiting Advanced:**](/hub/kong-inc/rate-limiting-advanced/) +This plugin does not support the `cluster` strategy in Hybrid mode. The `redis` +strategy must be used instead. +* [**OAuth 2.0 Authentication:**](/hub/kong-inc/oauth2/) This plugin is not +compatible with Hybrid mode. For its regular workflow, the plugin needs to both +generate and delete tokens, and commit those changes to the database, which is +not possible with CP/DP separation. + +### Custom Plugins + +Custom plugins (either your own plugins or third-party plugins that are not +shipped with Kong) need to be installed on both the Control Plane and the Data +Plane in Hybrid mode. + +### Load Balancing + +Currently, there is no automated load balancing for connections between the +Control Plane and the Data Plane. You can load balance manually by using +multiple Control Planes and redirecting the traffic using a TCP proxy. + +## Readonly Status API endpoints on Data Plane + +Several readonly endpoints from the [Admin API](/gateway/{{page.release}}/admin-api/) +are exposed to the [Status API](/gateway/{{page.release}}/reference/configuration/#status_listen) on data planes, including the following: + +- [GET /upstreams/{upstream}/targets/](/gateway/{{page.release}}/admin-api/#list-targets) +- [GET /upstreams/{upstream}/health/](/gateway/{{page.release}}/admin-api/#show-upstream-health-for-node) +- [GET /upstreams/{upstream}/targets/all/](/gateway/{{page.release}}/admin-api/#list-all-targets) +- GET /upstreams/{upstream}/targets/{target} + +Please refer to [Upstream objects](/gateway/{{page.release}}/admin-api/#upstream-object) in the Admin API documentation for more information about the +endpoints. diff --git a/app/gateway/2.6.x/plan-and-deploy/kong-user.md b/app/gateway/2.6.x/plan-and-deploy/kong-user.md new file mode 100644 index 000000000000..95fbf007bbab --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/kong-user.md @@ -0,0 +1,60 @@ +--- +title: Running Kong as a Non-Root User +--- + +After installing {{site.base_gateway}} on a GNU/Linux system, you can +configure Kong to run as the built-in `kong` user and group instead of `root`. +This makes the Nginx master and worker processes run as the built-in `kong` +user and group, overriding any settings in the +[`nginx_user`](/gateway/{{page.release}}/reference/configuration/#nginx_user) +configuration property. It is also possible to run Kong as a custom non-root user. + +{:.important} +> **Important:** The Nginx master process needs to run as `root` for +Nginx to execute certain actions (for example, to listen on the privileged +port 80). +

    +> Although running Kong as the `kong` user and group +does provide more security, we advise that a system and network +administration evaluation be performed before making this decision. Otherwise, +Kong nodes might become unavailable due to insufficient permissions to execute +privileged system calls in the operating system. + +## Prerequisites + +{{site.ee_product_name}} is installed on one of the following Linux distributions: +* [Amazon Linux 1 or 2](/gateway/{{page.release}}/install-and-run/amazon-linux/) +* [CentOS](/gateway/{{page.release}}/install-and-run/centos/) +* [RHEL](/gateway/{{page.release}}/install-and-run/rhel/) +* [Ubuntu](/gateway/{{page.release}}/install-and-run/ubuntu/) + +## Run {{site.base_gateway}} as the built-in kong user + +When {{site.base_gateway}} is installed with a package management system such as `APT` or `YUM`, a default `kong` user and a default `kong` group are created. All the files installed by the package are owned by the `kong` user and group. + +1. Switch to the built-in `kong` user: + + ```sh + $ su kong + ``` +2. Start Kong: + + ```sh + kong start + ``` + +## Run {{site.base_gateway}} as a custom non-root user + +It is also possible to run Kong as a custom non-root user. Since all the files installed by the {{site.base_gateway}} package are owned by the `kong` group, a user that belongs to that group should be permitted to perform the same operations as the `kong` user. + +1. Add the user to the `kong` group + + ```sh + sudo usermod -aG kong your-user + ``` + +2. Start Kong: + + ```sh + kong start + ``` diff --git a/app/gateway/2.6.x/plan-and-deploy/kubernetes-deployment-options.md b/app/gateway/2.6.x/plan-and-deploy/kubernetes-deployment-options.md new file mode 100644 index 000000000000..7c77af173dba --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/kubernetes-deployment-options.md @@ -0,0 +1,160 @@ +--- +title: Kubernetes Deployment Options +badge: enterprise +--- + +The {{site.kic_product_name}} translates Kubernetes resources into +{{site.base_gateway}} configuration. {{site.base_gateway}} uses that +configuration to route and control traffic. + +The [kong-gateway][enterprise-download] proxy image supports DB-less +operation and is recommended for all deployments. +* [DB-less installation with the {{site.kic_product_name}}][k4k8s-enterprise-install] +* [Database-backed installation with or without the {{site.kic_product_name}}](/gateway/{{page.release}}/install-and-run/helm/) + +### Migrating to 2.1.x and up + +Existing users of the `kong-enterprise-k8s` image who want to use 2.1.x or later +should switch to the `kong-gateway` image. + +If you encounter issues after switching images, please +[contact Enterprise Support][support]. + +## DB-less versus database-backed deployments + +When using {{site.base_gateway}} with {{site.kic_product_name}}, the source +of truth for Kong's configuration is +the Kubernetes configuration in etcd: Kong's custom Kubernetes resources, +ingresses, and services provide the information necessary for the ingress +controller to configure Kong. This differs from Kong deployments that do not +use an ingress controller, where configuration in the database or DB-less +config file is the source of truth. + +In traditional deployments, Kong's database (PostgreSQL or Cassandra) provides +a persistent store of configuration available to all Kong nodes to ensure +consistent proxy behavior across the cluster that is not affected by node +restarts. Because etcd provides this functionality in Kong for Kubernetes +deployments, it is not necessary to run an additional database, reducing +maintenance and infrastructure requirements. + +While running {{site.base_gateway}} with {{site.kic_product_name}} +does not require a database, it is fully compatible +with PostgreSQL and requires it for some features. etcd still remains the +source of truth in database-backed deployments: the controller translates +Kubernetes resources from etcd into Kong configuration and inserts them into +the database via the Admin API. + +## Choosing between DB-less or database-backed deployments + +In general, DB-less deployments are simpler to maintain and require less +resources to run. +These deployments must set `KONG_DATABASE=off` in their environment variables. + +Database-backed deployments offer a wider range of features. Review the +sections below to determine if your use case requires a feature that is not +available in DB-less deployments. + +### Feature availability + +Some Enterprise features are not available in DB-less deployments. +Use a database-backed deployment if you want to use: + +* Dev Portal +* Teams (RBAC) +* Workspaces + +The following features have support in DB-less mode, but +work differently than in DB-backed modes: + +* Kong Manager (read-only) +* Vitals (using [Prometheus][vitals-prometheus] or [InfluxDB][vitals-influxdb] + strategies) + +When {{site.base_gateway}} is configured by the ingress controller, some +functionality in these features is different from traditional deployments: + +* Instead of using Kong Manager, proxy configuration is managed by the + controller, and you provide configuration via Kubernetes resources. +* Because the controller creates proxy configuration on behalf of users, you do + not need to interact with the Admin API directly. Kong's own RBAC + implementation isn't required for typical Kong for Kubernetes deployments, as + they do not expose the Admin API; only the controller can access it. + Kubernetes-level RBAC rules and namespaces should be used to restrict what + configuration administrators can create. +* Ingress controller instances create configuration in a single workspace only + (`default` by default). To use multiple workspaces, deploy + multiple controller instances, setting the `CONTROLLER_KONG_WORKSPACE` + environment variable to the workspace that instance should use. These + instances should set `CONTROLLER_INGRESS_CLASS` to unique values for each + instance to avoid creating duplicate configuration in workspaces. Note that + if controller instances are deployed outside the Kong pod the Admin API must + be exposed, and users should enable RBAC with workspace admin users for the + controllers. Set `CONTROLLER_KONG_ADMIN_TOKEN` to the RBAC user's token. +* The controller cannot manage configuration for features that require a + database: it cannot create workspaces, Dev Portal content, admins, etc. These + features must be configured manually through the Admin API or Kong Manager. + +### Plugin compatibility + +Not all plugins are compatible with DB-less operation. Review the +[list of supported plugins][supported-plugins] to see if you require a plugin +that needs a database. + +Third-party plugins are generally compatible with DB-less as long as they do +not create custom entities (i.e. they do not add new entities that users can +create and modify through the Admin API). + +### Manual configuration + +DB-less configuration must be supplied as a complete unit: it is not possible +to add or modify entities individually through the Admin API, or provide +partial configuration that is added to existing configuration. As such, all +configuration must be sourced from Kubernetes resources so that the ingress +controller can render it into a complete configuration. + +On database-backed deployments, users can create or modify configuration +through the Admin API. The ingress controller uses a tag (set by the +`CONTROLLER_KONG_ADMIN_FILTER_TAG` environment variable) to identify +configuration that it manages. While the controller will revert changes to +configuration with its tag, other configuration is left as-is. + +Although database-backed deployments can use controller-generated and +manually-added configuration simultaneously, Kong's recommended best practice +is to manage as much configuration through Kubernetes resources as possible. +Using both controller-managed and manual configuration can result in conflicts +between the two, and conflicts will prevent the controller from applying its +configuration. To minimize this risk: + +* Use the [admission webhook][admission-webhook] + to reject Kubernetes resources that conflict with other configuration, or are + otherwise invalid. +* Manually create configuration in a workspace that is not managed by the + controller. This avoids most conflicts, but not all: routes may still + conflict depending on your [route validation][route-validation] setting. + +Large numbers of consumers (and associated credentials) are the exception to +this rule: if your consumer count is in the tens of thousands, we recommend +that you create them and their credentials through the Admin API to reduce etcd +load. + +## Migrating between deployment types + +Because etcd is the source of truth for Kong's configuration, the ingress +controller can re-create Kong's proxy configuration even if the underlying +datastore changes. + +While most Kubernetes resources can be left unchanged when migrating between +deployment types, users must remove any KongPlugin resources that use +unavailable plugins when migrating from a database-backed deployment to a +DB-less deployment. No changes to Kubernetes resources are required if +migrating in the opposite direction. + +[enterprise-download]: https://hub.docker.com/r/kong/kong-gateway/ +[admission-webhook]: /kubernetes-ingress-controller/latest/deployment/admission-webhook +[route-validation]: /gateway/{{page.release}}/reference/configuration/#route_validation_strategy +[supported-plugins]:/kubernetes-ingress-controller/latest/references/plugin-compatibility +[k4k8s-enterprise-install]: /gateway/{{page.release}}/install-and-run/kubernetes +[k4k8s-with-enterprise-install]: /gateway/{{page.release}}/install-and-run/kubernetes +[vitals-prometheus]: /gateway/{{page.release}}/vitals/vitals-prometheus-strategy/ +[vitals-influxdb]: /gateway/{{page.release}}/vitals/vitals-influx-strategy/ +[support]: https://support.konghq.com/ diff --git a/app/gateway/2.6.x/plan-and-deploy/licenses/access-license.md b/app/gateway/2.6.x/plan-and-deploy/licenses/access-license.md new file mode 100644 index 000000000000..2a33c737898a --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/licenses/access-license.md @@ -0,0 +1,21 @@ +--- +title: Access Your Kong Gateway License +badge: enterprise +--- + +To enable Enterprise features, {{site.base_gateway}} requires a license file. +You will receive this file from Kong when you sign up for a +{{site.konnect_product_name}} Enterprise subscription. + +[Contact Kong](https://konghq.com/get-started) for more information. + +{:.note} +> **Note:** The free mode does not require a license. See +[{{site.base_gateway}} Licensing](/gateway/{{page.release}}/plan-and-deploy/licenses/) +for a feature comparison. + +Once a license has been deployed to a {{site.base_gateway}} node, retrieve it +using the [`/licenses` Admin API endpoint](/gateway/{{page.release}}/admin-api/licenses/examples/). + +If you have purchased a subscription but haven't received a license file, +contact your sales representative. diff --git a/app/gateway/2.6.x/plan-and-deploy/licenses/deploy-license.md b/app/gateway/2.6.x/plan-and-deploy/licenses/deploy-license.md new file mode 100644 index 000000000000..e87d3b3e86b8 --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/licenses/deploy-license.md @@ -0,0 +1,9 @@ +--- +title: Deploy an Enterprise License +badge: enterprise +--- + +Deploy an enterprise license to a {{site.base_gateway}} installation to gain access +to [Enterprise-specific features](/gateway/{{page.release}}/plan-and-deploy/licenses/). + +{% include_cached /md/enterprise/deploy-license.md heading="##" release=page.release %} diff --git a/app/gateway/2.6.x/plan-and-deploy/licenses/index.md b/app/gateway/2.6.x/plan-and-deploy/licenses/index.md new file mode 100644 index 000000000000..c260fc159fef --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/licenses/index.md @@ -0,0 +1,111 @@ +--- +title: Kong Gateway Licensing +badge: enterprise +--- + +{{site.base_gateway}} can be used with or without a license. For Enterprise +functionality, {{site.base_gateway}} enforces the presence and validity of a +{{site.konnect_product_name}} license file. + +| Feature | Free Mode | Enterprise Subscription | +|--------------------|:---------:|:-----------------------:| +| Manager | | | +| Admin API | | | +| Vitals | | | +| Dev Portal | | | +| Enterprise plugins | | | + +## Deploying the license file + +License file checking is done independently by each node as the Kong process +starts. No network connectivity is necessary to execute the license validation process. + +There are multiple ways to configure a license file on a {{site.base_gateway}} +node. The method you use may depend on your deployment type. + +* **Hybrid mode deployment:** The license file must be deployed to +control plane nodes. The control planes then distribute the license to the data +planes in their clusters. Use the [`/licenses`](/gateway/{{page.release}}/admin-api/licenses/reference/) +endpoint to apply the license to the control plane. + +* **Traditional deployment with no separate control plane:** License files must +be deployed to each node running {{site.base_gateway}}. Use any of the +provided configuration methods to apply the license. + +Here are the possible license configuration methods, in the order that +{{site.base_gateway}} checks for them: + +1. If present, the contents of the environmental variable `KONG_LICENSE_DATA` are used. +2. Kong will search in the default location `/etc/kong/license.json`. +3. If present, the contents of the file defined by the environment variable `KONG_LICENSE_PATH` is used. +4. Directly deploy a license using the `/licenses` Admin API endpoint. + +In this manner, the license file can be deployed either as a file on the node +filesystem, as an environmental variable, or through the `/licenses` Admin API +endpoint. The simplest method is using the Admin API. + +Note that unlike most other `KONG_*` environmental variables, the +`KONG_LICENSE_DATA` and `KONG_LICENSE_PATH` cannot be defined in-line as part +of any `kong` CLI commands. License file environmental variables must be +exported to the shell in which the Nginx process will run, ahead of the `kong` +CLI tool. + +For more information, see [Deploy Your License](/gateway/{{page.release}}/plan-and-deploy/licenses/deploy-license/). + +## Examining the license data on a {{site.base_gateway}} node + +Retrieve license data using the Admin API's `/licenses` endpoint, or through +the Admin GUI in Kong Manager. + +## License expiration + +When a license expires, you will still have access to your {{site.base_gateway}} +and its configuration. Any Enterprise-specific features will be locked, and +the Admin API will not be accessible until the license is either renewed or the +subscription is downgraded to the free mode. + +In the event of a downgrade, the Admin API will be unlocked, but Enterprise +features such Dev Portal, Enterprise plugins, and others will no +longer be accessible. + +### License expiration logs + +{{site.base_gateway}} logs the license expiration date on the following schedule: +* 90 days before: `WARN` log entry once a day +* 30 days before: `ERR` log entry once a day +* At and after expiration: `CRIT` log entry once a day + +## Troubleshooting + +When a valid license file is properly deployed, license file validation is a transparent operation; no additional output or logging data is written or provided. If an error occurs when attempting to validate the license, or the license data is not valid, an error message will be written to the console and logged to the Kong error log, followed by the process quitting. Below are possible error messages and troubleshooting steps to take: + +`license path environment variable not set` +: Neither the `KONG_LICENSE_DATA` nor the `KONG_LICENSE_PATH` environmental variables were defined, and no license file could be opened at the default license location (`/etc/kong/license.json`) + +`internal error` +: An internal error has occurred while attempting to validate the license. Such cases are extremely unlikely; contact Kong support to further troubleshoot. + +`error opening license file` +: The license file defined either in the default location, or using the `KONG_LICENSE_PATH` env variable, could not be opened. Check that the user executing the Nginx process (e.g., the user executing the Kong CLI utility) has permissions to read this file. + +`error reading license file` +: The license file defined either in the default location, or using the `KONG_LICENSE_PATH` env variable, could be opened, but an error occurred while reading. Confirm that the file is not corrupt, that there are no kernel error messages reported (e.g., out of memory conditions, etc). This is a generic error and is extremely unlikely to occur if the file could be opened. + +`could not decode license json` +: The license file data could not be decoded as valid JSON. Confirm that the file is not corrupt and has not been altered since you received it from Kong Inc. Try re-downloading and installing your license file from Kong Inc. +: If you still receive this error after reinstallation, contact Kong support. + +`invalid license format` +: The license file data is missing one or more key/value pairs. Confirm that the file is not corrupt and has not been altered since you received it from Kong Inc. Try re-downloading and installing your license file from Kong Inc. +: If you still receive this error after reinstallation, contact Kong support. + +`validation failed` +: The attempt to verify the payload of the license with the license's signature failed. Confirm that the file is not corrupt and has not been altered since you received it from Kong Inc. Try re-downloading and installing your license file from Kong Inc. +: If you still receive this error after reinstallation, contact Kong support. + +`license expired` +: The system time is past the license's `license_expiration_date`. + +`invalid license expiration date` +: The data in the `license_expiration_date` field is incorrectly formatted. Try re-downloading and installing your license file from Kong Inc. +: If you still receive this error after reinstallation, contact Kong support. diff --git a/app/gateway/2.6.x/plan-and-deploy/licenses/report.md b/app/gateway/2.6.x/plan-and-deploy/licenses/report.md new file mode 100644 index 000000000000..b444222f39bc --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/licenses/report.md @@ -0,0 +1,90 @@ +--- +title: Monitor License Usage +badge: enterprise +--- + +Obtain information about your {{site.base_gateway}} deployment, including license usage and deployment information using the **License Report** module. Share this information with Kong to perform a health-check analysis of product utilization and overall deployment performance to ensure your organization is optimized with the best license and deployment plan for your needs. + +How the license report module works: +* The license report module manually generates a report containing usage and deployment data by sending a request to an endpoint, as defined below. +* Share this report with your Kong representative to perform an analysis of your deployment. + +What the license report module **does not** do: +* The license report module does not automatically generate a report or send any data to any Kong servers. +* The license report module does not track or generate any data other than the data that is returned in the response after you send a request to the endpoint. + +## Generate a License Report +Run the license report module and share the output information with your Kong representative for a deployment analysis. + +**Prerequisites**: You must have Admin privileges to generate a license report. + +To generate a license report, from an HTTP client: + +{% navtabs %} +{% navtab JSON response %} + +For a JSON response, send an HTTP request to the Kong node endpoint +`/license/report`. For example, use this cURL command: + +```bash +curl {ADMIN_API_URL}/license/report +``` + +A JSON response returns, similar to the example below: + +```json +HTTP/1.1 200 OK +Access-Control-Allow-Credentials: true +Access-Control-Allow-Origin: http://localhost:8002 +Connection: keep-alive +Content-Length: 262 +Content-Type: application/json; charset=utf-8 +Date: Wed, 19 Feb 2020 05:54:23 GMT +Server: kong/1.3-enterprise-edition +Vary: Origin +X-Kong-Admin-Request-ID: 6fmfr4Zl3RGmOs5oY0HvT47zt0oDq54o +{ + "counters":{ + "req_cnt":22 + }, + "db_version":"postgres 9.5.20", + "kong_version":"1.3-enterprise-edition", + "license_key":"ASDASDASDASDASDASDASDASDASD_a1VASASD", + "rbac_users":0, + "services_count": 27, + "system_info":{ + "cores":6, + "hostname":"264da9b95dfa", + "uname":"Linux x86_64" + }, + "workspaces_count":1 +} +``` + +{% endnavtab %} +{% navtab TAR file %} + +For a TAR file, enter the following cURL command to make a call to the +Kong Admin API: + +```bash +curl {ADMIN_API_URL}/license/report -o response.json && tar -cf report-$(date +"%Y_%m_%d_%I_%M_%p").tar response.json +``` + +A license report file is generated and archived to a `*.tar` file. + +{% endnavtab %} +{% endnavtabs %} + +## Report Structure + +Field | Description +------|------------ +`counters.req_count` | Counts the number of requests made since the license creation date. +`db_version` | The type and version of the datastore {{site.base_gateway}} is using. +`kong_version` | The version of the {{site.base_gateway}} instance. +`license_key` | An encrypted identifier for the current license key. If no license is present, the field displays as `UNLICENSED`. +`rbac_users` | The number of users registered with through RBAC. +`services_count` | The number of configured services in the {{site.base_gateway}} instance. +`system_info` | Displays information about the system running {{site.base_gateway}}.

    • `cores`: Number of CPU cores on the node
    • `hostname`: Encrypted system hostname
    • `uname`: Operating system +`workspaces_count` | The number of workspaces configured in the {{site.base_gateway}} instance. diff --git a/app/gateway/2.6.x/plan-and-deploy/performance-testing-framework.md b/app/gateway/2.6.x/plan-and-deploy/performance-testing-framework.md new file mode 100644 index 000000000000..5e344d6a8f5d --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/performance-testing-framework.md @@ -0,0 +1,352 @@ +--- +title: Performance Testing Framework +badge: oss +--- + +The {{site.base_gateway}} codebase includes a performance testing framework. It allows Kong developers and users to evaluate the performance of Kong itself as well as +bundled or custom plugins, and plot frame graphs to debug performance bottlenecks. +The framework collects RPS (request per second) and latencies of Kong processing the request +to represent performance metrics under different workloads. + +The framework is implemented as an extension to Kong's integration test suite. + +## Installation + +The framework uses [busted](https://github.com/lunarmodules/busted) and some +Lua development dependencies of Kong. To set up the environment, +run `make dev` on your Kong repository to install all Lua dependencies. + +## Drivers + +Three "drivers" are implemented depending on different environments, accuracy +requirements, and setup complexity. + +| Driver | Test between git commits | Test between binary releases | Flamegraph | Test unreleased version | +|----------|--------------------------|------------------------------|------------|-------------------------| +| local | yes | | yes | yes | +| docker | yes | yes | | | +|terraform | yes | yes | yes | | + +- **local** Driver reuses users' local environment. It's faster to run, +but the RPS and latency number may be influenced by other local programs and thus inaccurate. + + * Requires Lua development dependencies of Kong, OpenResty, and `wrk` be installed. + * Requires SystemTap, kernel headers, and build chain to be installed if generating FlameGraph. + +- **docker** Driver is solely based on Docker images. It's the most convenient driver to setup +as it requires less dependencies. But it may also be influenced by other local programs +and Docker network performance. And it doesn't support FlameGraph generation. + +- **terraform** Driver runs in remote VM or bare metal machine. It's most accurate, +but it requires Terraform knowledge to operate and setup. + + * Requires the [Terraform](https://www.terraform.io/downloads.html) binary be installed. + * Requires git binary if testing between git commits. When testing between git commits, + the framework assumes the current directory is Kong's repo. It will stash your working + directory and unstash after test is finished. When using the docker or terraform driver, + the framework derives the base version of each commit and uses the matching Docker image or + Kong binary package and puts local source code inside. + +## Workflow + +Like Kong's integration tests, the performance test is written in Lua. Several +test cases can share the same Lua file. + +The following code snippet demonstrates a basic workflow for defining a workload and load testing Kong. + +```lua +local perf = require("spec.helpers.perf") + +perf.use_driver("docker") + +local versions = { "git:master", "2.4.0" } + +for _, version in ipairs(versions) do + describe("perf test for Kong " .. version .. " #simple #no_plugins", function() + local bp + lazy_setup(function() + local helpers = perf.setup() + + bp = helpers.get_db_utils("postgres", { + "routes", + "services", + }) + + local upstream_uri = perf.start_upstream([[ + location = /test { + return 200; + } + ]]) + + local service = bp.services:insert { + url = upstream_uri .. "/test", + } + + bp.routes:insert { + paths = { "/s1-r1" }, + service = service, + strip_path = true, + } + end) + + before_each(function() + perf.start_kong(version, { + --kong configs + }) + end) + + after_each(function() + perf.stop_kong() + end) + + lazy_teardown(function() + perf.teardown() + end) + + it("#single_route", function() + local results = {} + for i=1,3 do + perf.start_load({ + path = "/s1-r1", + connections = 1000, + threads = 5, + duration = 10, + }) + + ngx.sleep(10) + + local result = assert(perf.wait_result()) + + print(("### Result for Kong %s (run %d):\n%s"):format(version, i, result)) + results[i] = result + end + + print(("### Combined result for Kong %s:\n%s"):format(version, assert(perf.combine_results(results)))) + + perf.save_error_log("output/" .. version:gsub("[:/]", "#") .. "-single_route.log") + end) + end) +end +``` + +The test can be run as a normal busted-based test. Run it with `bin/busted path/to/this_file_spec.lua`. + +More examples can be found in the [spec/04-perf](https://github.com/Kong/kong/tree/master/spec/04-perf) folder in the Kong +repository. + +## Sample Output + +``` +### Result for Kong git:96326b894f712b5d03bb1bf7ac02d531f6128cd1 (run 1): +Running 10s test @ http://10.88.145.9:8000/s1-r1 + 5 threads and 1000 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 17.51ms 61.46ms 1.04s 98.99% + Req/Sec 14.31k 2.61k 20.80k 82.59% + 672831 requests in 10.07s, 154.07MB read + Socket errors: connect 0, read 0, write 0, timeout 246 +Requests/sec: 66803.45 +Transfer/sec: 15.30MB +### Result for Kong git:96326b894f712b5d03bb1bf7ac02d531f6128cd1 (run 2): +Running 10s test @ http://10.88.145.9:8000/s1-r1 + 5 threads and 1000 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 14.71ms 10.66ms 96.77ms 66.18% + Req/Sec 14.45k 1.79k 20.19k 70.80% + 718942 requests in 10.08s, 164.70MB read +Requests/sec: 71337.25 +Transfer/sec: 16.34MB +### Result for Kong git:96326b894f712b5d03bb1bf7ac02d531f6128cd1 (run 3): +Running 10s test @ http://10.88.145.9:8000/s1-r1 + 5 threads and 1000 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 14.47ms 10.13ms 82.81ms 66.57% + Req/Sec 14.60k 1.64k 22.98k 72.00% + 726452 requests in 10.07s, 166.42MB read +Requests/sec: 72141.41 +Transfer/sec: 16.53MB +### Combined result for Kong git:96326b894f712b5d03bb1bf7ac02d531f6128cd1: +RPS Avg: 70094.04 +Latency Avg: 15.52ms Max: 1040.00ms +``` + +With samples in [spec/04-perf](https://github.com/Kong/kong/tree/master/spec/04-perf), the RPS and latency +results, Kong error logs and FlameGraph files are saved to `output` directory under current directory. + +## API + +### `perf.use_driver` + +*syntax: perf.use_driver(name, options?)* + +Uses driver name, which must be one of "local", "docker" or "terraform". Additional +parameters for the driver can be specified in options as a Lua table. Throws error if any. + +Only the terraform driver expects an options parameter, which contains following keys: + +- **provider** The service provider name, right now only "equinix-metal". +- **tfvars** Terraform variables as a Lua table; for `equinix-metal` provider, +`packet_project_id` and `packet_auth_token` is required. + +### `perf.set_log_level` + +*syntax: perf.set_log_level(level)* + +Sets the log level; expect one of `"debug"`, `"info"`, `"notice"`, `"warn"`, `"error"` and +`"crit"`. The default log level is `"info"`. + +### `perf.set_retry_count` + +*syntax: perf.set_retry_count(count)* + +Sets retry time for each “driver" operation. By default every operation is retried 3 times. + +### `perf.setup` + +*syntax: helpers = perf.setup()* + +Prepares environment and returns the `spec.helpers` module. Throws error if any. + +The framework sets up some environment variables before importing `spec.helpers` modules. +The returned helper is just a normal `spec.helpers` module. Users can use the same pattern +in integration tests to setup entities in Kong. DB-less mode is currently not implemented. + +### `perf.start_upstream` + +Syntax: +``` +upstream_uri = perf.start_upstream(nginx_conf_blob) +``` + +Starts upstream (Nginx/OpenResty) with given `nginx_conf_blob`. Returns the upstream +URI accessible from Kong's view. Throws error if any. + +### `perf.start_kong` + +Syntax: +``` +perf.start_kong(version, kong_configs?) +``` + +Starts Kong with given version and Kong configurations in `kong_configs` as a Lua table. +Throws error if any. + +To select a git hash or tag, use `"git:"` as version. Otherwise, the framework +will treat the `version` as a release version and will download binary packages from +Kong's distribution website. + +### `perf.stop_kong` + +Syntax: +``` +perf.stop_kong() +``` + +Stops Kong. Throws error if any. + +### `perf.teardown` + +Syntax: +``` +perf.teardown(full?) +``` + +Teardown. Throws error if any. With the terraform driver, setting full to true terminates +all infrastructure, while by default it does cleanup only to speed up successive runs. + +### `perf.start_stapxx` + +Syntax: +``` +perf.start_stapxx(stapxx_file_name, arg?) +``` + +Starts the Stap++ script with `stapxx_file_name` exists in +[available stapxx scripts](https://github.com/Kong/stapxx/tree/kong/samples) +and additional CLI args. Throws error if any. + +This function blocks test execution until the `SystemTap` module is fully prepared and inserted into the +kernel. It should be called before `perf.start_load`. + +### `perf.start_load` + +Syntax: +``` +perf.start_load(options?) +``` + +Starts to send load to Kong using `wrk`. Throws error if any. Options is a Lua table that may contain the following: + +- **path** String request path; defaults to `/ `. +- **uri** Base URI exception path; defaults to `http://kong-ip:kong-port/`. +- **connections** Connection count; defaults to 1000. +- **threads** Request thread count; defaults to 5. +- **duration** Number of performance tests duration in seconds; defaults to 10. +- **script** Content of `wrk` script as string; defaults to nil. + +### `perf.wait_result` + +Syntax: +``` +result = perf.start_load(options?) +``` + +Waits for the load test to finish and returns the result as a string. Throws error if any. + +Currently, this function waits indefinitely, or until both `wrk` and Stap++ processes exit. + +### `perf.combine_results` + +Syntax: +``` +combined_result = perf.combine_results(results, …) +``` + +Calculates multiple results returned by `perf.wait_result` and returns their average and min/max. +Throws error if any. + +### `perf.generate_flamegraph` + +Syntax: +``` +perf.generate_flamegraph(path, title?) +``` + +Generates a FlameGraph with title and saves to path. Throws error if any. + +### `perf.save_error_log` + +Syntax: +``` +perf.save_error_log(path) +``` + +Saves Kong error log to path. Throws error if any. + +## Customization + +### Add new test suite + +All tests are stored in `spec/04-perf/01-rps` and `spec/04-perf/02-flamegraph` of the Kong repository. +Add a new file under one of the directories and put `#tags` in the test description. + +### Add new provider in terraform + +Users can use the terraform driver in most major service providers as long as +it's supported by Terraform. The following contracts are made between the framework and terraform module: + +The terraform files are stored in `spec/fixtures/perf/terraform/`. + +Two instances are provisioned, one for running Kong and another for running an upstream +and load (worker). A firewall allows bidirectional traffic between the two instances +and from the public internet. Both instances run Ubuntu 20.04/focal. + +An SSH key to login into both instances exists or will be created in +`spec/fixtures/perf/terraform//id_rsa`. The logged-in user has root privilege. + +The following are terraform output variables: + +- **kong-ip** Kong node public IP. +- **kong-internal-ip** Kong node internal IP (if unavailable, provide kong-ip). +- **worker-ip** Worker node public IP. +- **worker-internal-ip** Worker node internal IP (if unavailable, provide worker-ip). diff --git a/app/gateway/2.6.x/plan-and-deploy/security/db-encryption.md b/app/gateway/2.6.x/plan-and-deploy/security/db-encryption.md new file mode 100644 index 000000000000..ff02bb2b631a --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/security/db-encryption.md @@ -0,0 +1,320 @@ +--- +title: Keyring and Data Encryption +badge: enterprise +--- + +{{site.base_gateway}} provides a mechanism to store sensitive data fields, such as consumer secrets, in an encrypted format within the database (PostgreSQL or Cassandra). This provides for encryption-at-rest security controls in a Kong cluster. + +This functionality provides transparent, symmetric encryption of sensitive data fields at rest. _Transparency_ refers to the fact that, when enabled, encryption/decryption of data is done on-the-fly by Kong immediately before writing/immediately after reading from the database. Responses generated by the Admin API containing sensitive fields continue to show data as plaintext, and runtime elements of Kong (such as plugins) that require access to sensitive fields do so transparently, without requiring additional configuration. + +## Getting Started + +This document provides a brief introduction to leveraging {{site.base_gateway}} symmetric database encryption to store sensitive configuration data in a Kong cluster. This document covers necessary Kong configuration settings and key management lifecycle procedures when using database encryption in `cluster` mode. This mode offers the simplest method to getting started, as it requires no external dependencies. + +### Generate a Management RSA Key Pair + +Before enabling database encryption, we strongly recommend you generate an RSA key pair for use in exporting and recovering keyring material. If keyring material is lost, it is impossible to recover any sensitive data fields written to the database with a key on that keyring. + +Generating an RSA key pair is straightforward via the `openssl` CLI: + +```bash +$ openssl genrsa -out key.pem 2048 +$ openssl rsa -in key.pem -pubout -out cert.pem +``` + +This key pair will be provided to Kong in order to facilitate exporting and re-importing the keyring. The public `cert.pem` and private `key.pem` should be stored securely in accordance with your existing secrets management policies. Details on secure storage of RSA key pairs is outside the scope of this documentation. + +### Configure Kong for database encryption + +Enabling data encryption in Kong requires modifying the Kong configuration. Set the following values in `kong.conf`: + +``` +keyring_enabled = on +keyring_strategy = cluster +keyring_public_key = /path/to/generated/cert.pem +keyring_private_key = /path/to/generated/key.pem +``` + +Or via environmental variables: + +``` +export KONG_KEYRING_ENABLED=on +export KONG_KEYRING_STRATEGY=cluster +export KONG_KEYRING_PUBLIC_KEY=/path/to/generated/cert.pem +export KONG_KEYRING_PRIVATE_KEY=/path/to/generated/key.pem +``` + +All nodes in the Kong cluster should share the same `keyring_enabled` and `keyring_strategy` configuration values. Not every node needs to be provided the management RSA key pair, as that key pair is only used for backup and recovery processes. It does not need to be present for regular database read/write operations. + +Note that the user under which Kong worker processes run must have read access to the public and private keys in order to be able to perform keyring export and import operations. This user is defined by the `nginx_user` Kong configuration option. We recommend restricting access to these files as tightly as possible. For example: + +```bash +$ chown : /path/to/generated/cert.pem /path/to/generated/key.pem +$ chmod 400 /path/to/generated/cert.pem /path/to/generated/key.pem +``` + +When testing, you can also set `keyring_blob_path` in kong.conf or `KONG_KEYRING_BLOB_PATH` +using environmental variables to specify a path to dump known keys. The dumped keys are +encrypted with the public RSA key defined in the `keyring_public_key` Kong configuration +value, and are automatically loaded during Kong start. + +### Start Kong + +Once all Kong nodes in the cluster have been configured, start each node: + +```bash +$ kong start +``` + +When encryption is enabled on a Kong node, it checks the status of the cluster keyring on boot. If it detects that no keys are present in the keyring, it will generate a key automatically. This process allows encryption/decryption operations to begin immediately. + +For all other nodes, the generated key will be automatically distributed within a few seconds. + +Note that encryption keys are held _only_ in memory, and do not persist past a restart of the Kong process (e.g., running `kong restart`). Because of this limitation, you must export the keyring following its initialization. Otherwise, if all Kong nodes in a cluster restart simultaneously, any sensitive fields written with the keyring become unrecoverable. Key material still persists after a soft reload of Kong (i.e., `kong reload`). + +### Verify the Cluster Keyring + +With the keyring enabled and Kong started, verify the contents of the keyring: + + +```bash +$ curl -s localhost:8001/keyring | jq +{ + "ids": [ + "LaW1urRQ" + ], + "active": "LaW1urRQ" +} +``` + +Note that in this example, the value `LaW1urRQ` is the _ID_ of the key, not the key material itself. + +### Export the Keyring + +Before going further, export the keyring. The exported material can be re-imported to the cluster in the event of an outage, or to restore a previously-deleted key: + +```bash +$ curl -XPOST -s localhost:8001/keyring/export | jq +{ + "data": "eyJrIjoiV1JZeTdubDlYeFZpR3VVQWtWTXBcL0JiVW1jMWZrWHluc0dKd3N4M1c0MlIxWE5XM05lZ05sdFdIVmJ1d0ZnaVZSTnFSdmM1WERscGY3b0NIZ1ZDQ3JvTFJ4czFnRURhOXpJT0tVV0prM2lhd0VLMHpKTXdwRDd5ZjV2VFYzQTY0Y2UxcVl1emJoSTI4VUZ1ZExRZWljVjd2T3BYblVvU3dOY3IzblhJQWhyWlcxc1grWXE3aHM1RzhLRXY2OWlRamJBTXAwbHZmTWNFWWxTOW9NUjdnSm5xZWlST0J1Q09iMm5tSXg0Qk1uaTJGalZzQzBtd2R2dmJyYWxYa3VLYXhpRWZvQm9EODk3MEtVcDYzY05lWGdJclpjang4YmJDV1lDRHlEVmExdGt5c0g1TjBJM0hTNDRQK1dyT2JkcElCUk5vSVZVNis1QWdcLzdZM290RUdzN1E9PSIsImQiOiIxWEZJOXZKQ05CTW5uVTB5c0hQenVjSG5nc2c5UURxQmcxZ3g1VVYxNWNlOEVTTlZXTmthYm8zdlUzS2VRTURcL0RUYXdzZCtJWHB5SllBTkRtanZNcytqU2lrVTFiRkpyMEVcLzBSRlg2emJrT0oybTR2bXlxdVE9PSIsIm4iOiJUUmRLK01Qajh6MkdHTmtyIn0=" +} + +``` + +The response generated is an opaque blob containing the keyring, encrypted with +a randomly-generated symmetric key. This random key is encrypted with the public +RSA key defined via the `keyring_public_key` Kong configuration value. + +The exported keyring should be stored in a safe location for disaster recovery +purposes. It is not designed to be modified or decrypted before being used during +a disaster recovery process. + +### Exercise the Encryption Routines + +Create a Consumer with a basic-auth credential. At this point, the `password` field of the basic-auth credential will be symmetrically encrypted before it is written to the database (in addition to being hashed by the basic-auth plugin, which is done by the plugin regardless of whether keyring encryption is enabled): + +```bash +$ curl -s localhost:8001/consumers -d username=bob | jq +{ + "custom_id": null, + "created_at": 1576518610, + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9", + "tags": null, + "username": "bob", + "type": 0 +} +``` + +```bash +$ curl -s localhost:8001/consumers/bob/basic-auth -d username=bob -d password=supersecretpassword | jq +{ + "created_at": 1576518704, + "consumer": { + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9" + }, + "id": "fc46ce48-c1d6-4078-9f51-5a777350a8a2", + "password": "da61c0083b6d19ef3db2490d0da96a71572da0fa", + "username": "bob" +} +``` + +Note that the returned `password` field in the API response is not the encrypted value; database encryption does not modify responses generated by the Admin API. This allows existing workflows to continue in the same form, while providing encryption at rest security under the hood. We can verify this by examining the value stored in the database: + +``` +kong=# select id,password from basicauth_credentials; + id | password +--------------------------------------+--------------------------------------------------------------------------------------------------------------------------- + fc46ce48-c1d6-4078-9f51-5a777350a8a2 | $ke$1$-LaW1urRQ-0f5b1ee8ddeefca1a1d75125-53f158a5f619133a2113692a7057e2b91fa947321de4480d452dd42c36bc9ef8aa6499cd429db6d7 +(1 row) +``` + +We can also verify that reading back the credential after it has been created behaves as expected: + +```bash +$ curl -s localhost:8001/consumers/bob/basic-auth/fc46ce48-c1d6-4078-9f51-5a777350a8a2 | jq +{ + "created_at": 1576518704, + "consumer": { + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9" + }, + "id": "fc46ce48-c1d6-4078-9f51-5a777350a8a2", + "password": "da61c0083b6d19ef3db2490d0da96a71572da0fa", + "username": "bob" +} +``` + +### Exercise Importing the Keyring + +Restart Kong and re-import the previously exported keyring: + +```bash +$ kong restart +``` + +```bash +$ curl localhost:8001/keyring/import -d data= +``` + +This operation requires that the `keyring_private_key` point to the private RSA +key associated with the public key used during the initial keyring export. Once +this is complete, Admin API operations that require the keyring for encryption/ +decryption can be verified: + +```bash +$ curl -s localhost:8001/consumers/bob/basic-auth/fc46ce48-c1d6-4078-9f51-5a777350a8a2 | jq +{ + "created_at": 1576518704, + "consumer": { + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9" + }, + "id": "fc46ce48-c1d6-4078-9f51-5a777350a8a2", + "password": "da61c0083b6d19ef3db2490d0da96a71572da0fa", + "username": "bob" +} +``` + +### Rotating Key Material + +As noted above, Kong supports rotating keys by allowing for multiple keys to exist on the keyring at the same time. This allows for data fields written by one key to be read back, while a fresher encryption key is used for write operations. Rotating keys is a matter of importing or generating a new key into the keyring, and marking it as active. Arbitrary key material can be imported via the `/keyring/import` material, or Kong can generate a new key via `/keyring/generate` endpoint: + +```bash +$ curl -XPOST -s localhost:8001/keyring/generate +{ + "key": "t6NWgbj3g9cbNVC3/D6oZ2Md1Br5gWtRrqb1T2FZy44=", + "id": "8zgITLQh" +} +``` + +Note that as a convenience the raw key material is returned from this endpoint call. + +Once a new key is present in the keyring, activate the key's ID: + +```bash +$ curl -s localhost:8001/keyring/activate -d key=8zgITLQh +``` + +Kong can write new sensitive data fields with the current `active` key, and read previously written fields in the database with the prior key, provided that key is in the keyring. Kong automatically selects the appropriate key to use when decrypting fields from the database. + +At this point, it is encouraged to take another backup of the keyring via the `/keyring/export` Admin API endpoint. + +### Rotating Encrypted Data Fields + +Once the keyring has updated, existing encrypted fields can rotate to use the new active key. To accomplish this rotation, issue a PATCH request to the entity in question: + +```bash +$ # curl -XPATCH -s localhost:8001/consumers/bob/basic-auth/fc46ce48-c1d6-4078-9f51-5a777350a8a2 -d password=adifferentsecretpassword | jq +{ + "created_at": 1576518704, + "consumer": { + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9" + }, + "id": "fc46ce48-c1d6-4078-9f51-5a777350a8a2", + "password": "cc7274e94e41f3e00c238ff8712d1a83693f2a89", + "username": "bob" +} +``` + +Again, note that the encryption behavior is transparent to the Admin API response. Under the hood, Kong reads the entity's `password` field with a read-only encryption key. As part of the PATCH process, Kong writes the `password` field back to the database with the new `active` key. To verify this process, examine the raw contents of the database: + +``` +kong=# select id,password from basicauth_credentials; + id | password +--------------------------------------+--------------------------------------------------------------------------------------------------------------------------- + fc46ce48-c1d6-4078-9f51-5a777350a8a2 | $ke$1$-8zgITLQh-b8d28531252241e6b95907e4-0768a9a4baaa2c777d9406d4e3098d813be55ae82c4c849182b06b9c5954704c6290c9e677bcd693 +(1 row) +``` + +Note that the key identifier within the password data blob has been updated. This rotation mechanism allows organizations to meet specific compliance needs around key management rotation and retention policies. + +Currently, encrypted fields must undergo a direct write operation in order to rotate the encrypted field. Future releases of Kong may contain helper API operations to automate this process. + +### Exploring Missing Keyring Material Behavior + +As a test, stop all Kong nodes in the cluster, and restart one Kong node again, but do not import the keyring material. The behavior of attempting to read an entity with an encrypted field now changes: + +```bash +$ time curl -s localhost:8001/consumers/bob/basic-auth/fc46ce48-c1d6-4078-9f51-5a777350a8a2 +{"message":"An unexpected error occurred"} +real 0m24.811s +user 0m0.017s +sys 0m0.006s +``` + +When the Kong node restarts, it sends a broadcast request for the keyring, but as no other nodes are present in the cluster (or no other nodes had the keyring available), Kong is unable to decrypt the `password` field on the credential. Because Kong has an eventually-consistent clustering model, it makes several attempts to request the keyring and allows for delays in hearing responses from another cluster node; thus, the request takes several seconds to complete before finally failing. + +## Implementation Details + +### Encryption/Decryption + +{{site.base_gateway}} uses 256-bit AES encryption in GCM mode. Cryptographic nonce values for each encryption routine execution are derived from the kernel CSPRNG (`/dev/urandom`). The AES routines used by Kong are provided by the OpenSSL library bundled with the {{site.base_gateway}} package. + +### Key Generation and Lifecycle + +{{site.base_gateway}}'s keyring handling mechanisms allow for more than one key to be present on any given Kong node at a time. Each key may be used to read encrypted fields from the database, but one and only one key at any given time is used to write encrypted fields back to the data store. This process allows for a key rotation mechanism wherein new keyring material is introduced, and older keys may be present for a time to allow rotating previously-encrypted fields. + +Through the kernel CSPRNG, Kong derives keyring material generated through the `/keyring/generate` Admin API endpoint. Kong stores keyring material in a shared memory zone that all Kong worker processes access. To prevent key material from being written to disk as part of memory paging operations, we recommend that swap be disabled on systems running Kong + +When operating in `cluster` mode, keyring material propagates automatically among all nodes in the Kong cluster. Because Kong nodes do not have a notion of direct peer-to-peer communication, the underlying datastore (Cassandra or PostgreSQL) serves as a communication channel to transmit messages. When a Kong node starts, it generates an ephemeral RSA key pair. The node's public keys propagate to all other active nodes in the cluster. When an active node sees a message request for keyring material, it wraps the in-memory keyring material in the presented public key, and transmits the payload back over the central messaging channel provided by the underlying data store. This process allows each node in the cluster to broadcast keyring material to new nodes, without sending key material in plaintext over the wire. This model requires that at least one node be running at all times within the cluster; a failure of all nodes requires manually re-importing the keyring to one node during an outage recovery. + +### Encrypted Fields + +The keyring module encrypts the following fields at rest: + +* `key` fields of `certificate` objects (corresponding to the private key of a TLS certificate) +* `password` fields of `basic-auth` plugin credential objects (note that passwords are also hashed by a one-way hashing function) +* `key` fields of `key-auth-enc` plugin credential objects +* `client_id` and `client_secret` fields of the `openid-connect` plugin +* `aws_key` and `aws_secret` fields of the `aws-lambda` plugin + +## Vault Integration + +Kong's keyring mechanism can integrate directly with [HashiCorp Vault](https://www.vaultproject.io/) for keyring storage and versioning. In this model, Kong nodes read keyring material directly from a Vault KV secrets engine, rather than generating and disseminating keyring material around the cluster. + +To configure Kong to use Vault for keyring storage, set the `keyring_strategy` configuration value to `vault`. Leveraging Vault also requires defining a host, mount point, and token for Vault access. See the Kong configuration reference for more details. + +### Key Format + +Kong leverages version 2 of the [Vault KV secrets engine](https://www.vaultproject.io/docs/secrets/kv/kv-v2.html). This process allows for the same versioning and key rotation mechanisms that the `cluster` keyring strategy provides. Each version of a KV secrets entry must contain both an `id` field, and a `key` field, e.g.: + +```json +{ + "key": "t6NWgbj3g9cbNVC3/D6oZ2Md1Br5gWtRrqb1T2FZy44=", + "id": "8zgITLQh" +} +``` + +To provide consistent consumption of all Vault KV secrets, the underlying symmetric key is derived as the SHA256 of the `key` component of the secret value. Take note of this derivation when extending or re-using symmetric encryption keys from other systems. This derivation also implies that the `key` field can contain any arbitrary data, as Kong hashes the contents before importing the material into the keyring. + +To provide a new key, add a new version to the Vault secrets engine at the configured path. The `current_version` of the Vault secret denotes the active key in the keyring. See the [KV v2 documentation](https://www.vaultproject.io/docs/secrets/kv/kv-v2.html) for more detail. + +### Vault Permissions + +In order to communicate with Vault, Kong must be provided a Vault token for access. The token must be associated with a policy that allows the `read` and `list` actions on the path where keyring secrets are stored. Kong does not write keyring material to the Vault cluster. + +### Syncing the Keyring + +Kong reads the keyring material from Vault when the Kong process starts. Any changes to the Vault KV store are not reflected on the Kong node until Kong syncs with Vault via the `/keyring/vault/sync` Admin API endpoint. This allows Kong to receive a Vault token with a low TTL, as the list and read operation only occur once. + +### Keyring on hybrid mode + +Because Keyring encrypts the data in the database, it means it doesn't encrypt data on Kong data plane nodes that run without a database and get data from the control plane. diff --git a/app/gateway/2.6.x/plan-and-deploy/security/kong-security-update-process.md b/app/gateway/2.6.x/plan-and-deploy/security/kong-security-update-process.md new file mode 100644 index 000000000000..537a3b4f3604 --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/security/kong-security-update-process.md @@ -0,0 +1,19 @@ +--- +title: Kong Security Update Process +--- + +## Reporting a Vulnerability + +If you have found a vulnerability or a potential vulnerability in the Kong gateway or other Kong software, or know of a publicly disclosed security vulnerability, please immediately let us know by emailing [security@konghq.com](mailto:security@konghq.com). We'll send a confirmation email to acknowledge your report, and we'll send an additional email when we've identified the issue positively or negatively. + +Once a report is received, we will investigate the vulnerability and assign it a [CVSS](https://www.first.org/cvss/) score which will determine the timeline for the development of an appropriate fix. + +While the fix development is underway, we ask that you do not share or publicize an unresolved vulnerability with third parties. If you responsibly submitted a vulnerability report, we will do our best to acknowledge your report in a timely fashion and notify you of the estimated timeline for a fix. + +## Fix Development Process + +If a discovered vulnerability with a CVSS score above 4.0 (medium severity or higher) affects the latest major release of the Kong gateway or other Kong software, then we will work to develop a fix in the most timely fashion. The work and communication around the fix will happen in private channels, and a delivery estimate will be given to the vulnerability reporter. Once the fix is developed and verified, a new patch version will be released by Kong for each supported {{site.base_gateway}} release and for the current release of the open source gateway. We will disclose the vulnerability as appropriate. + +Discovered vulnerabilities with a CVSS score below 4.0 (low severity) will follow the same fix development and release process but with a less urgent timeline. + +Vulnerabilities affecting upstream projects (e.g. NGINX, OpenResty, OpenSSL...) will receive fixes as per the upstream project's disclosure timeline. diff --git a/app/gateway/2.6.x/plan-and-deploy/security/start-kong-securely.md b/app/gateway/2.6.x/plan-and-deploy/security/start-kong-securely.md new file mode 100644 index 000000000000..6a5b35a3ddb7 --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/security/start-kong-securely.md @@ -0,0 +1,99 @@ +--- +title: Start Kong Gateway Securely +badge: enterprise +--- + +To secure the Admin API or Kong Manager, a Super Admin account is +required. + +The Super Admin has the ability to invite other Admins and +restrict their access based on Permissions of Roles within +Workspaces. + +The first Super Admin account is created during database migrations +following the guide below. It may only be added once. + +## Prerequisites + +After [installing {{site.base_gateway}}](/gateway/{{page.release}}/install-and-run/), +either modify the configuration file or set environment variables for +the following properties: + +* `enforce_rbac` will force all Admin API requests to require a +`Kong-Admin-Token`. The Admin associated with the `Kong-Admin-Token` +must have adequate Permissions in order for the request to succeed. + +* If using Kong Manager, select the type of authentication that Admins +should use to log in. For the purpose of this guide, `admin_gui_auth` +may be set to `basic-auth`. See +[Securing Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/) for other types +of authentication. + +For a simple configuration to use for the subsequent Getting +Started guides: + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = {"secret":"secret","storage":"kong","cookie_secure":false} +admin_listen = 0.0.0.0:8001, 0.0.0.0:8444 ssl +``` + +⚠️**Important:** the Sessions Plugin requires a secret and is configured securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#session-security), and see [example configurations](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +## Step 1 + +Set a password for the Super Admin. This environment variable must +be present in the environment where database migrations will run. + +{:.important} +> **Important**: Setting your Kong password (`KONG_PASSWORD`) using a value containing four ticks (for example, `KONG_PASSWORD="a''a'a'a'a"`) causes a PostgreSQL syntax error on bootstrap. To work around this issue, do not use special characters in your password. + +``` +$ export KONG_PASSWORD= +``` + +This automatically creates a user, `kong_admin`, and a password that +can be used to log in to Kong Manager. This password may also be +used as a `Kong-Admin-Token` to make Admin API requests. + +**Note:** only one Super Admin may be created using this method, and only +on a fresh installation with an empty database. If one is not created during migrations, +follow [this guide](/gateway/{{page.release}}/configure/auth/rbac/add-admin/) to remediate. + +Future migrations will not update the password or create additional Super Admins. +To add additional Super Admins it is necessary to +[invite a new user as a Super Admin in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/super-admin/). + +## Step 2 + +Issue the following command to prepare your data store by running the Kong migrations: + +``` +$ kong migrations bootstrap [-c /path/to/kong.conf] +``` + +## Step 3 + +Start Kong: + +``` +$ kong start [-c /path/to/kong.conf] +``` + +**Note:** the CLI accepts a configuration option (`-c /path/to/kong.conf`) +allowing you to point to [your own configuration](/gateway/{{page.release}}/reference/configuration/#configuration-loading). + +## Step 4 + +To test that {{site.base_gateway}} has successfully started with a Super Admin, +visit Kong Manager's URL. By default, it is on port `:8002`. + +The username is `kong_admin` and the password is the one set in +[Step 1](#step-1). diff --git a/app/gateway/2.6.x/plan-and-deploy/sizing-guidelines.md b/app/gateway/2.6.x/plan-and-deploy/sizing-guidelines.md new file mode 100644 index 000000000000..b6ee2d944ab4 --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/sizing-guidelines.md @@ -0,0 +1,191 @@ +--- +title: Resource Sizing Guidelines +--- + +This document discusses the performance characteristics of +{{site.base_gateway}}, and offers recommendations on sizing for +resource allocation based on expected {{site.base_gateway}} configuration and +traffic patterns. + +These recommendations are a baseline guide only. Specific tuning or +benchmarking efforts should be undertaken for performance-critical environments. + +## General resource guidelines + +### {{site.base_gateway}} resources + +{{site.base_gateway}} is designed to operate in a variety of deployment +environments. It has no minimum system requirements to operate. + +Resource requirements vary substantially based on configuration. The following +high-level matrices offer a guideline for determining system requirements +based on overall configuration and performance requirements. + +Consider the following simplified examples, where latency and throughput requirements are considered on a per-node basis. This table has rough usage requirement estimates: + +| Size | Number of Configured Entities | Latency Requirements | Throughput Requirements | Usage Pattern | +|---|---|---|---|---| +| Small | < 100 | < 100 ms | < 500 RPS | Dev/test environments; latency-insensitive gateways | +| Medium | < 1000 | < 20 ms | < 2500 RPS | Production clusters; greenfield traffic deployments | +| Large | < 10000 | < 10 ms | < 10000 RPS | Mission-critical clusters; legacy & greenfield traffic; central enterprise-grade gateways | + +### Database resources + +We do not provide any hard numbers for database sizing (DB sizing), as it +depends on your particular setup. Sizing varies based on: +* Traffic +* Number of nodes +* Enabled features: for example, Vitals, or if rate limiting uses a +database or Redis +* Number and rate of change of configured entities +* The rate at which {{site.base_gateway}} processes are started and restarted within the cluster +* The size of {{site.base_gateway}}'s [in-memory cache](#in-memory-caching) + +{{site.base_gateway}} intentionally relies on the database as little as +possible. To access configuration, {{site.base_gateway}} executes a spiky +access pattern to its backing database. This means that {{site.base_gateway}} +only reads configuration from the database when a node first starts, or +configuration for a given entity changes. + +Everything in the database is meant to be read infrequently and held in memory +as long as possible. Therefore, database resource requirements are lower than +those of compute environments running {{site.base_gateway}}. + +Query patterns are typically simple and follow schema indexes. Provision +sufficient database resources in order to handle spiky query patterns. + +There are [settings](/gateway/{{page.release}}/reference/configuration/#datastore-section/) +that you can adjust to keep database access minimal (also see [in-memory caching](#in-memory-caching)), or +[keep {{site.base_gateway}} operational](https://support.konghq.com/support/s/article/Keeping-Kong-Functional-During-DB-Down-Times) +if the DB is down for maintenance. If you choose to keep the database +operational during downtimes, vitals data is not written to the +database during this time. + +### Cluster resource allocations + +Based on the expected size and demand of the cluster, we recommend +the following resource allocations as a starting point: + +| Size | CPU | RAM | Typical Cloud Instance Sizes | +|---|---|---|---|---| +| Small | 1-2 cores | 2-4 GB | **AWS**: t3.medium
    **GCP**: n1-standard-1
    **Azure**: Standard A1 v2 | +| Medium | 2-4 cores | 4-8 GB | **AWS**: m5.large
    **GCP**: n1-standard-4
    **Azure**: Standard A1 v4 | +| Large | 8-16 cores | 16-32 GB | **AWS**: c5.xlarge
    **GCP**: n1-highcpu-16
    **Azure**: F8s v2 | + +We strongly discourage the use of throttled cloud instance types (such as the +AWS `t2` or `t3` series of machines) in large clusters, as CPU throttling would +be detrimental to {{site.base_gateway}}'s performance. We also recommend +testing and verifying the bandwidth availability for a given instance class. +Bandwidth requirements for {{site.base_gateway}} depend on the shape and volume +of traffic flowing through the cluster. + +### In-memory caching +We recommend defining the `mem_cache_size` configuration as large as possible, +while still providing adequate resources to the operating system and any other +processes running adjacent to {{site.base_gateway}}. This configuration allows +{{site.base_gateway}} to take maximum advantage of the in-memory cache, and +reduce the number of trips to the database. + +Each {{site.base_gateway}} worker process maintains its own memory allocations, +and must be accounted for when provisioning memory. By default, one worker +process runs per number of available CPU cores. We recommend allowing for +around **500MB** of memory allocated per worker process. + +For example, on a machine with 4 CPU cores and 8 GB of RAM available, we recommend allocating between 4-6 GB to cache via the `mem_cache_size` directive, depending on what other processes are running alongside {{site.base_gateway}}. + +## Scaling dimensions + +{{site.base_gateway}} is designed to handle large volumes of request +traffic and proxying requests with minimal latency. Understanding how various +configuration scenarios impacts request traffic, and the {{site.base_gateway}} +cluster itself, is a crucial step in successfully deploying +{{site.base_gateway}}. + +{{site.base_gateway}} measures performance in the following dimensions: + +* **Latency** refers to the delay between the downstream client +sending a request and receiving a response. {{site.base_gateway}} measures +latency introduced into the request in terms of microseconds or milliseconds. +Increasing the number of Routes and Plugins in a {{site.base_gateway}} cluster +increases the amount of latency that's added to each request. +* **Throughput** refers to the number of +requests that {{site.base_gateway}} can process in a given time span, typically +measured in seconds or minutes. + +These dimensions have an inversely proportional relationship +when all other factors remain the same: decreasing the latency introduced into +each request allows the maximum throughput in {{site.base_gateway}} to +increase, as there is less CPU time spent handling each request, and more +CPU available for processing traffic as a whole. {{site.base_gateway}} is +designed to scale horizontally to be able to add more overall compute power for +configurations that add substantial latency into requests, while needing to +meet specific throughput requirements. + +{{site.base_gateway}}'s maximum throughput is a CPU-bound dimension, and minimum +latency is memory-bound. +* **Latency-sensitive workload**: making more memory available for database caching +is more beneficial than adding more compute power to the cluster. +* **Throughput-sensitive workload**: these workloads are dependant on both adequate +memory and CPU resources, but adding more +compute power by scaling {{site.base_gateway}} vertically or horizontally is +the better choice, as it provides near-unlimited throughput capacity. In this +scenario, adding more cache memory would not increase maximum throughput by +much. + +Performance benchmarking and optimization as a whole is a complex exercise that +must account for a variety of factors, including those external to +{{site.base_gateway}}, such as the behavior of upstream services, or the health +of the underlying hardware on which {{site.base_gateway}} is running. + +## Performance characteristics + +There are a number of factors that impact {{site.base_gateway}}'s performance, +including: + +* **Number of configured Routes and Services**: Increasing the count of Routes +and Services on the cluster requires more CPU to evaluate the request. +However, {{site.base_gateway}}'s request router can handle running at large +scale. We've seen clusters of {{site.base_gateway}} nodes serving tens of +thousands of Routes with minimal impact to latency as a result of request route +evaluation. + +* **Number of configured Consumers and Credentials**: Consumer and credential +data is stored in {{site.base_gateway}}'s datastore (either PostgreSQL or +Cassandra, or the `kong.yml` file in DB-less environments). +{{site.base_gateway}} caches this data in memory to reduce database load and +latency during request processing. Increasing the count of Consumers and +Credentials requires more memory available for {{site.base_gateway}} to hold +data in cache. If there is not enough memory available to cache all requested +database entities, request latency increases as {{site.base_gateway}} needs to +query the database more frequently to satisfy requests. + +* **Number of configured Plugins**: Increasing the count of Plugins on the +cluster requires more CPU to iterate through plugins during request +processing. Executing plugins comes with a varying cost depending on the nature +of the plugin. For example, a lightweight authentication plugin like `key-auth` +requires less resource availability than a plugin that performs complex +transformations of an HTTP request or response. + +* **Cardinality of configured Plugins**: _Cardinality_ is the number +of distinct plugin types that are configured on the cluster. For example, a +cluster with one each of `ip-restriction`, `key-auth`, `bot-detection`, +`rate-limiting`, and `http-log` plugins has a higher plugin cardinality than a +cluster with one thousand `rate-limiting` plugins applied at the route level. +With each additional plugin type added to the cluster, {{site.base_gateway}} +spends more time evaluating whether to execute a given plugin for a given +request. Increasing the cardinality of configured plugins requires more CPU +power, as the process to evaluate plugins is a CPU-constrained task. + +* **Request and response size**: Requests with large HTTP bodies, either in the +request or response, take longer to process, as {{site.base_gateway}} must +buffer the request to disk before proxying it. This allows +{{site.base_gateway}} to handle a large volume of traffic without running out +of memory, but the nature of buffered requests can result in increased latency. + +* **Number of configured Workspaces**: Increasing the count of Workspaces on the +cluster requires more CPU to evaluate each request, and more memory +available for the cache to hold Workspace configuration and metadata. The +impact of increasing the number of Workspaces on the cluster is also affected +by the cardinality of configured plugins on the cluster. There is an +exponential impact on request throughput capacity within the cluster +as the cardinality of plugins _and_ the number of Workspaces increases. diff --git a/app/gateway/2.6.x/plan-and-deploy/systemd.md b/app/gateway/2.6.x/plan-and-deploy/systemd.md new file mode 100644 index 000000000000..729b1f2cba9e --- /dev/null +++ b/app/gateway/2.6.x/plan-and-deploy/systemd.md @@ -0,0 +1,153 @@ +--- +title: Control Kong Gateway through systemd +--- + +This document includes instructions on how to integrate {{site.base_gateway}} +with systemd for Debian and RPM based packages. + +Note that some of the supported GNU/Linux distributions for {{site.base_gateway}} +may not have adopted systemd as their default init system +(for example, CentOS 6 and RHEL 6). For the following instructions, it is +assumed that {{site.base_gateway}} has already been +[installed and configured](/gateway/{{page.release}}/install-and-run) on a +systemd-supported GNU/Linux distribution. + +## systemd commands for working with {{site.base_gateway}} + +### Start {{site.base_gateway}} + +```bash +# For {{site.base_gateway}} +sudo systemctl start kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl start kong +``` + +### Stop {{site.base_gateway}} + +```bash +# For {{site.base_gateway}} +sudo systemctl stop kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl stop kong +``` + +### Start {{site.base_gateway}} at system boot + +**Enable starting {{site.base_gateway}} automatically at system boot** + +```bash +# For {{site.base_gateway}} +sudo systemctl enable kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl enable kong +``` + +**Disable starting {{site.base_gateway}} automatically at system boot** + +```bash +# For {{site.base_gateway}} +sudo systemctl disable kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl disable kong +``` + +### Restart {{site.base_gateway}} + +```bash +# For {{site.base_gateway}} +sudo systemctl restart kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl restart kong +``` + +### Query {{site.base_gateway}} status + +```bash +# For {{site.base_gateway}} +sudo systemctl status kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl status kong +``` + +## Customize the {{site.base_gateway}} unit file + +The official systemd service is located at `/lib/systemd/system/kong-enterprise-edition.service` for +{{site.base_gateway}}, or at `/lib/systemd/system/kong.service` for {{site.ce_product_name}}. + +For scenarios where customizations are needed (for example, configuring Kong +or modifying the service file behavior), we recommend creating another service +at `/etc/systemd/system/kong-enterprise-edition.service` for +{{site.base_gateway}}, or at `/etc/systemd/system/kong.service` for +{{site.ce_product_name}}, to avoid conflicts upon reinstalling or upgrading Kong. + +All environment variables prefixed with `KONG_` and capitalized will override the settings specified in the `/etc/kong/kong.conf.default` file. For example: `log_level = debug` in the .conf file translates to the `KONG_LOG_LEVEL=debug` environment variable. + +You can also choose use a configuration file instead of environment variables. In this case, modify the `ExecStartPre` systemd directive to execute `kong prepare` with the `-c` argument to point to your configuration file. For example, if you have a custom configuration file at `/etc/kong/kong.conf`, modify the `ExecStartPre` directive as follows: + +``` +ExecStartPre=/usr/local/bin/kong prepare -p /usr/local/kong -c /etc/kong/kong.conf +``` + +When linking non environment files using the `EnvironmentFile` systemd directive, note that the systemd parser will only recognize environment variables assignments. For example, if one of the Kong's default configuration files are linked (`/etc/kong/kong.conf.default` and `/etc/kong.conf`), non environment variables assignments in the file could lead to systemd errors. In this case, systemd will not allow the Kong service to be started. For this reason, we recommend specifying an `EnvironmentFile` other than the default ones: + +``` +EnvironmentFile=/etc/kong/kong_env.conf +``` + +### Logging to syslog and journald + +In this case, adding the below `Environment` systemd directives to your customized systemd service file at `/etc/systemd/system/kong-enterprise-edition.service` will do it: + +``` +Environment=KONG_PROXY_ACCESS_LOG=syslog:server=unix:/dev/log +Environment=KONG_PROXY_ERROR_LOG=syslog:server=unix:/dev/log +Environment=KONG_ADMIN_ACCESS_LOG=syslog:server=unix:/dev/log +Environment=KONG_ADMIN_ERROR_LOG=syslog:server=unix:/dev/log +``` + +To view the journald logs: + +```bash +# For {{site.base_gateway}} +journalctl -u kong-enterprise-edition + +# For {{site.ce_product_name}} +journalctl -u kong +``` + +To view the syslog logs: + +```bash +tail -F /var/log/syslog +``` + +### Customize Kong's Nginx instance using the Nginx directive injection system + +To use the [injection system](/gateway/{{page.release}}/reference/configuration/#injecting-individual-nginx-directives) with environment variables, add the below `Environment` systemd directive to your custom service at `/etc/systemd/system/kong-enterprise-edition.service` ({{site.base_gateway}}) or `/etc/systemd/system/kong.service` ({{site.ce_product_name}}). Note the quoting rules defined by systemd to specify an environment variable containing spaces: + +``` +Environment="KONG_NGINX_HTTP_OUTPUT_BUFFERS=4 64k" +``` + +### Customize Kong's Nginx instance using --nginx-conf + +To use the [`--nginx-conf`](/gateway/{{page.release}}/reference/configuration/#custom-nginx-templates) argument, modify the `ExecStartPre` systemd directive to execute `kong prepare` with the `--nginx-conf` argument. For example, if you have a custom template at `/usr/local/kong/custom-nginx.template`, modify the `ExecStartPre` directive as follows: + +``` +ExecStartPre=/usr/local/bin/kong prepare -p /usr/local/kong --nginx-conf /usr/local/kong/custom-nginx.template +``` + +### Customize Kong's Nginx instance including files via the injected Nginx directives + +To [include files via the injected Nginx directives](/gateway/{{page.release}}/reference/configuration/#including-files-via-injected-nginx-directives) with environment variables, add the below `Environment` systemd directive to your custom service at `/etc/systemd/system/kong-enterprise-edition.service` ({{site.base_gateway}}) or `/etc/systemd/system/kong.service` ({{site.ce_product_name}}): + +``` +Environment=KONG_NGINX_HTTP_INCLUDE=/path/to/your/my-server.kong.conf +``` diff --git a/app/gateway/2.6.x/plugin-development/access-the-datastore.md b/app/gateway/2.6.x/plugin-development/access-the-datastore.md new file mode 100644 index 000000000000..cf62b5e015ab --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/access-the-datastore.md @@ -0,0 +1,67 @@ +--- +title: Plugin Development - Accessing the Datastore +book: plugin_dev +chapter: 5 +--- + +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 PostgreSQL). 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 PostgreSQL) 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 = "httpbin", + url = "https://httpbin.konghq.com", +}) + +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). + +[Plugin Development Kit]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.6.x/plugin-development/admin-api.md b/app/gateway/2.6.x/plugin-development/admin-api.md new file mode 100644 index 000000000000..c421cc1edd3f --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/admin-api.md @@ -0,0 +1,168 @@ +--- +title: Plugin Development - Extending the Admin API +book: plugin_dev +chapter: 8 +--- + +{:.note} +> **Notes:** +> * This chapter assumes that you have a relative + knowledge of [Lapis](http://leafo.net/lapis/). +> * The Admin API extensions are available only + for HTTP plugins, not Stream plugins. + +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 +``` + +## Add 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. In this example, +the functions are provided by the `kong.api.endpoints` library. + +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. + +[Admin API]: /gateway/{{page.release}}/admin-api/ diff --git a/app/gateway/2.6.x/plugin-development/custom-entities.md b/app/gateway/2.6.x/plugin-development/custom-entities.md new file mode 100644 index 000000000000..67f38d5fd72e --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/custom-entities.md @@ -0,0 +1,670 @@ +--- +title: Plugin Development - Storing Custom Entities +book: plugin_dev +chapter: 6 +--- + +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.url}}), 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 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 PostgreSQL, 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. + +## Add 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 PostgreSQL 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 PostgreSQL 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 PostgreSQL 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 PostgreSQL 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 PostgreSQL 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/master/kong/plugins/key-auth/migrations). + + +## Define 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, + admin_api_name = "key-auths", + admin_api_nested_name = "key-auth", + 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. +
    generate_admin_apiboolean (optional) + Whether to auto-generate admin api for the entity or not. By default the admin api is generated for all + daos, including custom ones. If you want to create a fully customized admin api for the dao or + want to disable auto-generation for the dao altogether, set this option to false. +
    admin_api_nameboolean (optional) + When generate_admin_api is enabled the admin api auto-generator uses the name + to derive the collection urls for the auto-generated admin api. Sometimes you may want to name the + collection urls differently from the name. E.g. with DAO keyauth_credentials + we actually wanted the auto-generator to generate endpoints for this dao with alternate and more + url-friendly name key-auths, e.g. http://<KONG_ADMIN>/key-auths instead of + http://<KONG_ADMIN>/keyauth_credentials). +
    admin_api_nested_nameboolean (optional) + Similar to admin_api_name the admin_api_nested_name specifies the name for + a dao that admin api auto-generator creates in nested contexts. You only need to use this parameter + if you are not happy with name or admin_api_name. Kong for legacy reasons + have urls like http://<KONG_ADMIN>/consumers/john/key-auth where key-auth + does not follow plural form of http://<KONG_ADMIN>/key-auths. admin_api_nested_name + enables you to specify different name in those cases. +
    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 addition 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.release | 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.release | 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.release | 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`. + +### Select 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 +``` + +### Iterate 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. + +### Insert 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`. + +### Update 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. + +### Upsert 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. + +### Delete 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 +``` + +## Cache 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.url}}). + +[Admin API]: /gateway/{{page.release}}/admin-api/ +[Plugin Development Kit]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.6.x/plugin-development/custom-logic.md b/app/gateway/2.6.x/plugin-development/custom-logic.md new file mode 100644 index 000000000000..5c10468827dc --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/custom-logic.md @@ -0,0 +1,378 @@ +--- +title: Plugin Development - Implementing Custom Logic +book: plugin_dev +chapter: 3 +--- + +{:.note} +> **Note**: This chapter assumes that you are familiar with +[Lua](http://www.lua.org/). + +A {{site.base_gateway}} 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 {{site.base_gateway}}. To do so, the file +`kong.plugins..handler` must return a table with one or +more functions with predetermined names. Those functions will be +invoked by {{site.base_gateway}} at different phases when it processes traffic. + +The first parameter they take is always `self`. All functions except `init_worker` +can receive a second parameter which is a table with the plugin configuration. + +## Module + +``` +kong.plugins..handler +``` + +## Available contexts + +If you define any of the following functions in your `handler.lua` +file you'll implement custom logic at various entry-points +of {{site.base_gateway}}'s execution life-cycle: + +- **[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.
    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. +| `response` | [access] | Replaces both `header_filter()` and `body_filter()`. Executed after the whole response has been received from the upstream service, but before sending any part of it to the client. +| `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. This function 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. + +{:.note} +> **Note:** If a module implements the `response` function, {{site.base_gateway}} will automatically activate the "buffered proxy" mode, as if the [`kong.service.request.enable_buffering()` function][enable_buffering] had been called. Because of a current Nginx limitation, this doesn't work for HTTP/2 or gRPC upstreams. + +To reduce unexpected behaviour changes, {{site.base_gateway}} does not start if a plugin implements both `response` and either `header_filter` or `body_filter`. + +- **[Stream Module]** *is used for Plugins written for TCP and UDP 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. +| `certificate` | [ssl_certificate] | Executed during the SSL certificate serving phase of the SSL handshake. + +All of those functions, except `init_worker`, take one parameter which is given +by {{site.base_gateway}} 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.url}}). + +Note that UDP streams don't have real connections. {{site.base_gateway}} will consider all +packets with the same origin and destination host and port as a single +connection. After a configurable time without any packet, the connection is +considered closed and the `log` function is executed. + +[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 +[enable_buffering]: /gateway/{{page.release}}/pdk/kong.service.request/#kongservicerequestenable_buffering + + +## handler.lua specifications + +{{site.base_gateway}} processes requests in **phases**. A plugin is a piece of code that gets +activated by {{site.base_gateway}} as each phase is executed while the request gets proxied. + +Phases are limited in what they can do. For example, the `init_worker` phase +does not have access to the `config` parameter because that information isn't +available when kong is initializing each worker. + +A plugin's `handler.lua` must return a table containing the functions it must +execute on each phase. + +{{site.base_gateway}} can process HTTP and stream traffic. Some phases are executed +only when processing HTTP traffic, others when processing stream, +and some (like `init_worker` and `log`) are invoked by both kinds of traffic. + +In addition to functions, a plugin must define two fields: + +* `VERSION` is an informative field, not used by {{site.base_gateway}} directly. It usually + matches the version defined in a plugin's Rockspec version, when it exists. +* `PRIORITY` is used to sort plugins before executing each of their phases. + Plugins with a higher priority are executed first. See the + [plugin execution order](#plugins-execution-order) below + for more info about this field. + +The following example `handler.lua` file defines custom functions for all +the possible phases, in both http and stream traffic. It has no functionality +besides writing a message to the log every time a phase is invoked. Note +that a plugin doesn't need to provide functions for all phases. + +```lua +local CustomHandler = { + VERSION = "1.0.0", + PRIORITY = 10 +} + +function CustomHandler:init_worker() + -- Implement logic for the init_worker phase here (http/stream) + kong.log("init_worker") +end + + +function CustomHandler:preread(config) + -- Implement logic for the preread phase here (stream) + kong.log("preread") +end + + +function CustomHandler:certificate(config) + -- Implement logic for the certificate phase here (http/stream) + kong.log("certificate") +end + +function CustomHandler:rewrite(config) + -- Implement logic for the rewrite phase here (http) + kong.log("rewrite") +end + +function CustomHandler:access(config) + -- Implement logic for the rewrite phase here (http) + kong.log("access") +end + +function CustomHandler:header_filter(config) + -- Implement logic for the header_filter phase here (http) + kong.log("header_filter") +end + +function CustomHandler:body_filter(config) + -- Implement logic for the body_filter phase here (http) + kong.log("body_filter") +end + +function CustomHandler:log(config) + -- Implement logic for the log phase here (http/stream) + kong.log("log") +end + +-- return the created table, so that Kong can execute it +return CustomHandler +``` + +Note that in the example above we are using Lua's `:` shorthand syntax for +functions taking `self` as a first parameter. An equivalent unshortened version +of the `access` function would be: + +``` lua +function CustomHandler.access(self, config) + -- Implement logic for the rewrite phase here (http) + kong.log("access") +end +``` + +The plugin's logic doesn't need to be all defined inside the `handler.lua` file. +It can be split into several Lua files (also called *modules*). +The `handler.lua` module can use `require` to include other modules in your plugin. + +For example, the following plugin splits the functionality into three files. +`access.lua` and `body_filter.lua` return functions. They are in the same +folder as `handler.lua`, which requires and uses them to build the plugin: + +```lua +-- handler.lua +local access = require "kong.plugins.my-custom-plugin.access" +local body_filter = require "kong.plugins.my-custom-plugin.body_filter" + +local CustomHandler = { + VERSION = "1.0.0", + PRIORITY = 10 +} + +CustomHandler.access = access +CustomHandler.body_filter = body_filter + +return CustomHandler +``` + +```lua +-- access.lua +return function(self, config) + kong.log("access phase") +end +``` + +```lua +-- body_filter.lua +return function(self, config) + kong.log("body_filter phase") +end +``` + +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). {{site.base_gateway}} 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 {{site.base_gateway}}. + +When you are trying to implement some logic that needs to interact with {{site.base_gateway}} +(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, {{site.base_gateway}} 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.). + +{% navtabs %} +{% navtab Open-source or Free mode %} + +The following list includes all plugins bundled with open-source +{{site.base_gateway}} or {{site.base_gateway}} running in Free mode. + +{:.note} +> **Note:** The correlation-id plugin's execution order is different depending +on whether you're running {{site.base_gateway}} in Free mode or using the +open-source package. + +The current order of execution for the bundled plugins is: + +Plugin | Priority +----------------------------|---------- +pre-function | `+inf` +correlation-id | 100001 +zipkin | 100000 +bot-detection | 2500 +cors | 2000 +session | 1900 +jwt | 1005 +oauth2 | 1004 +key-auth | 1003 +ldap-auth | 1002 +basic-auth | 1001 +hmac-auth | 1000 +grpc-gateway | 998 +ip-restriction | 990 +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 +grpc-web | 3 +request-termination | 2 +correlation-id | 1 +post-function | -1000 + +{% endnavtab %} +{% navtab Enterprise %} +The following list includes all plugins bundled with a {{site.base_gateway}} +Enterprise subscription. + +The current order of execution for the bundled plugins is: + +Plugin | Priority +----------------------------|---------- +pre-function | `+inf` +correlation-id | 100001 +zipkin | 100000 +exit-transformer | 9999 +bot-detection | 2500 +cors | 2000 +route-by-header | 2000 +session | 1900 +oauth2-introspection | 1700 +acme | 1007 +mtls-auth | 1006 +jwt | 1005 +degraphql | 1005 +oauth2 | 1004 +vault-auth | 1003 +key-auth | 1003 +key-auth-enc | 1003 +ldap-auth | 1002 +ldap-auth-advanced | 1002 +basic-auth | 1001 +openid-connect | 1000 +hmac-auth | 1000 +request-validator | 999 +jwt-signer | 999 +grpc-gateway | 998 +application-registration | 995 +ip-restriction | 990 +request-size-limiting | 951 +acl | 950 +opa | 920 +rate-limiting-advanced | 902 +graphql-rate-limiting-advanced | 902 +rate-limiting | 901 +response-ratelimiting | 900 +jq | 811 +request-transformer-advanced | 802 +request-transformer | 801 +response-transformer-advanced | 800 +route-transformer-advanced | 800 +response-transformer | 800 +kafka-upstream | 751 +aws-lambda | 750 +azure-functions | 749 +graphql-proxy-cache-advanced | 100 +proxy-cache-advanced | 100 +proxy-cache | 100 +forward-proxy | 50 +prometheus | 13 +canary | 13 +http-log | 12 +statsd | 11 +statsd-advanced | 11 +datadog | 10 +file-log | 9 +udp-log | 8 +tcp-log | 7 +loggly | 6 +kafka-log | 5 +syslog | 4 +grpc-web | 3 +request-termination | 2 +mocking | -1 +post-function | -1000 + +{% endnavtab %} +{% endnavtabs %} +[lua-nginx-module]: https://github.com/openresty/lua-nginx-module +[pdk]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.6.x/plugin-development/distribution.md b/app/gateway/2.6.x/plugin-development/distribution.md new file mode 100644 index 000000000000..5fd373399915 --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/distribution.md @@ -0,0 +1,282 @@ +--- +title: Plugin Development - (un)Installing your plugin +book: plugin_dev +chapter: 10 +--- + +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 + + +## Install 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 of the following paths. + +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. + +### 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, for example +`http://myrepository.lan/rocks/my-plugin-0.1.0-1.all.rock`. + +### 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. + +### 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. + +For example, if the plugin `something` is located on the file system and the +handler file is in the following directory: + + /usr/local/custom/kong/plugins//handler.lua + +The location of the `kong` directory is `/usr/local/custom`, so the +proper path setup would be: + + lua_package_path = /usr/local/custom/?.lua;; + +#### Multiple plugins + +If you want 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". + +You can also set this property via its environment variable +equivalent: `KONG_LUA_PACKAGE_PATH`. + + +## Load the plugin + +1. 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 + + You can also set this property via its environment variable equivalent: + `KONG_PLUGINS`. + +1. Update the `plugins` directive for each node in your Kong cluster. + +1. Restart Kong to apply the plugin: + + kong restart + + Or, if you want to apply a plugin without stopping Kong, you can use this: + + kong prepare + kong reload + + +## 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. + +1. 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 + +2. Then, you should see the following log for each plugin being loaded: + + [debug] Loading plugin + + +## Remove 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. + + + +## Distribute 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][example-rockspec] using the `builtin` +build type to define modules in Lua notation and their corresponding file. + +For more information about the format, see the LuaRocks +[documentation on rockspecs][rockspec]. + + +## 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 Kong can't load +the `handler.lua` source file from the file system. To resolve, make sure that +the [`lua_package_path`](/gateway/{{page.release}}/reference/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 and 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. + +--- + +[rockspec]: https://github.com/keplerproject/luarocks/wiki/Creating-a-rock +[plugin-template]: https://github.com/Kong/kong-plugin +[example-rockspec]: https://github.com/Kong/kong-plugin/blob/master/kong-plugin-myplugin-0.1.0-1.rockspec diff --git a/app/gateway/2.6.x/plugin-development/entities-cache.md b/app/gateway/2.6.x/plugin-development/entities-cache.md new file mode 100644 index 000000000000..667cd65db5f8 --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/entities-cache.md @@ -0,0 +1,344 @@ +--- +title: Plugin Development - Caching Custom Entities +book: plugin_dev +chapter: 7 +--- + +Your plugin may need to frequently access custom entities (explained in the +[previous chapter]({{page.book.previous.url}})) 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 +``` + +## Cache custom entities + +Once you have defined your custom entities, you can cache them in-memory in +your code by using the [kong.cache](/gateway/{{page.release}}/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. + +### Update or delete 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 want your cached entities to 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, + admin_api_name = "key-auths", + admin_api_nested_name = "key-auth", + 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](/gateway/{{page.release}}/reference/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. +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.url}}). + +[Admin API]: /gateway/{{page.release}}/admin-api/ +[Plugin Development Kit]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.6.x/plugin-development/file-structure.md b/app/gateway/2.6.x/plugin-development/file-structure.md new file mode 100644 index 000000000000..be9b4eb969b1 --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/file-structure.md @@ -0,0 +1,115 @@ +--- +title: Plugin Development - File Structure +book: plugin_dev +chapter: 2 +--- + +{:.note} +> **Note**: This chapter assumes that you are familiar with +[Lua](http://www.lua.org/). + +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 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`](/gateway/{{page.release}}/reference/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](/gateway/{{page.release}}/reference/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. + +[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/gateway/2.6.x/plugin-development/index.md b/app/gateway/2.6.x/plugin-development/index.md new file mode 100644 index 000000000000..9a14c070de69 --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/index.md @@ -0,0 +1,31 @@ +--- +title: Plugin Development - Introduction +book: plugin_dev +chapter: 1 +--- + +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** (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. + +[lua-nginx-module]: https://github.com/openresty/lua-nginx-module +[Plugin Development Kit]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.6.x/plugin-development/plugin-configuration.md b/app/gateway/2.6.x/plugin-development/plugin-configuration.md new file mode 100644 index 000000000000..01bbf41e4562 --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/plugin-configuration.md @@ -0,0 +1,402 @@ +--- +title: Plugin Development - Plugin Configuration +book: plugin_dev +chapter: 4 +--- + +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, or Consumer. + +For example, a user performs the following request: + +```bash +$ curl -X POST http://localhost: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. +| `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 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 + }, + { + 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](/gateway/{{page.release}}/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://localhost: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]. + +[Admin API]: /gateway/{{page.release}}/admin-api +[Plugin Development Kit]: /gateway/{{page.release}}/pdk +[the Key-Auth plugin source code]: https://github.com/Kong/kong/blob/master/kong/plugins/key-auth/schema.lua diff --git a/app/gateway/2.6.x/plugin-development/tests.md b/app/gateway/2.6.x/plugin-development/tests.md new file mode 100644 index 000000000000..46d4841937b9 --- /dev/null +++ b/app/gateway/2.6.x/plugin-development/tests.md @@ -0,0 +1,102 @@ +--- +title: Plugin Development - Writing tests +book: plugin_dev +chapter: 9 +--- + +If you are serious about your plugin, 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](https://github.com/lunarmodules/busted/) running with the +[resty-cli](https://github.com/openresty/resty-cli) interpreter, though you are +free to use a different one. 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.konghq.com" + } + + 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 +``` + +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. + +For a real-world example, see the +[Key-Auth plugin specs](https://github.com/Kong/kong/tree/master/spec/03-plugins/09-key-auth). + diff --git a/app/gateway/2.6.x/reference/cli.md b/app/gateway/2.6.x/reference/cli.md new file mode 100644 index 000000000000..a74fa3b05ea3 --- /dev/null +++ b/app/gateway/2.6.x/reference/cli.md @@ -0,0 +1,360 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# the files in https://github.com/Kong/kong/tree/master/autodoc/cli +# +title: CLI Reference +source_url: https://github.com/Kong/kong/tree/master/autodoc/cli +--- + +## 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 top](#introduction) + +## 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 top](#introduction) + +--- + + +### 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. If a filename + is not given, ./kong.yml is used + by default. + + db_import Import a declarative config file into + the Kong database. + + db_export [] Export the Kong database into a + declarative config file. If a filename + is not given, ./kong.yml is used + by default. + + 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. + +``` + +{:.note} +> **Note:** `db_export` is only supported with open-source +{{site.base_gateway}} packages. + +[Back to top](#introduction) + +--- + + +### 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 top](#introduction) + +--- + + +### kong hybrid + +``` +Usage: kong hybrid COMMAND [OPTIONS] + +Hybrid mode utilities for Kong. + +The available commands are: + gen_cert [ ] Generate a certificate/key pair that is suitable + for use in hybrid mode deployment. + Cert and key will be written to + './cluster.crt' and './cluster.key' inside + the current directory unless filenames are given. + +Options: + -d,--days (optional number) Override certificate validity duration. + Default: 1095 days (3 years) + +``` + +[Back to top](#introduction) + +--- + +### 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. + The `reset` command erases all of the data + in Kong's database and deletes all of the schemas. + migrate-community-to-enterprise Migrates Kong Community entities to + Kong Enterprise in the default + workspace. +upgrade-workspace-table Outputs a script to be run on the db to + upgrade the entity for 2.x workspaces + implementation. +reinitialize-workspace-entity-counters Resets the entity counters from the + database entities. +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. + With 'migrate-community-to-enterprise', + it disables the workspace entities + check. + --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. +``` + +--- + + +### 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 top](#introduction) + +--- + + +### 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 top](#introduction) + +--- + + +### 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 top](#introduction) + +--- + + +### 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 top](#introduction) + +--- + +### kong runner +{:.badge .enterprise} + +``` +Usage: kong runner [file] [args] +Execute a lua file in a kong node. the `kong` variable is available to +reach the DAO, PDK, etc. The variable `args` can be used to access all +arguments (args[1] being the lua filename being run). +Example usage: + kong runner file.lua arg1 arg2 + echo 'print("foo")' | kong runner +``` + +--- + +### 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 top](#introduction) + +--- + + +### 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 top](#introduction) + +--- + + +### 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 top](#introduction) + +--- + + +[configuration-reference]: /gateway/{{page.release}}/reference/configuration/ diff --git a/app/gateway/2.6.x/reference/clustering.md b/app/gateway/2.6.x/reference/clustering.md new file mode 100644 index 000000000000..62a261fe1b8d --- /dev/null +++ b/app/gateway/2.6.x/reference/clustering.md @@ -0,0 +1,298 @@ +--- +title: Clustering Reference +--- + +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, and so on. 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. + +## 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 +``` + +## 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**. + +### Use read-only replicas when deploying Kong clusters with PostgreSQL + +When using PostgreSQL as the backend storage, you can optionally enable +Kong to serve read queries from a separate database instance. + +One of the common use cases of this feature is to deploy Kong with the +Amazon Aurora service as backend storage. Because Aurora natively supports +read-only instances, enabling the read-only connection support in Kong +greatly reduces the load on the main database instance since read-only +queries are no longer sent to it. + +To learn more about how to configure this feature, refer to the +[Datastore section](/gateway/{{page.release}}/reference/configuration/#datastore-section) +of the Configuration reference. + +## 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. + +## How to configure database caching? + +You can configure three properties in the Kong configuration file, the most +important one being `db_update_frequency`, which determine where your Kong +nodes stand on the performance versus consistency trade-off. + +Kong comes with default values tuned for consistency so that you can +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 means that the polling +job will execute more frequently, but that your Kong nodes will keep up +with changes you apply. A higher value means 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. + + +### 2. [db_update_propagation][db_update_propagation] (default: 0s) + + +If your database itself is eventually consistent (that is, 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 eventually 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. + + +### 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/PostgreSQL). 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. + +### 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 in 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. + +Setting the `cassandra_refresh_frequency` option to `0` is not advised, as a Kong +restart will be required to discover any changes to the Cassandra cluster topology. + +## Interacting with the cache via the Admin API + +If for some reason, you want 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. + +### 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. + +### Purge a node's cache + +**Endpoint** + +
    /cache
    + +**Response** + +``` +HTTP 204 No Content +``` + +**Note**: Be wary of using this endpoint on a node running in production with warm cache. +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). + + +[db_update_frequency]: /gateway/{{page.release}}/reference/configuration/#db_update_frequency +[db_update_propagation]: /gateway/{{page.release}}/reference/configuration/#db_update_propagation +[db_cache_ttl]: /gateway/{{page.release}}/reference/configuration/#db_cache_ttl diff --git a/app/gateway/2.6.x/reference/configuration.md b/app/gateway/2.6.x/reference/configuration.md new file mode 100644 index 000000000000..2bed06ba1dd1 --- /dev/null +++ b/app/gateway/2.6.x/reference/configuration.md @@ -0,0 +1,3690 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# the files in https://github.com/Kong/docs.konghq.com/tree/main/autodoc-conf-ee +# +title: Configuration Reference for Kong Gateway +source_url: https://github.com/Kong/kong-ee/edit/master/kong.conf.default +--- + +## 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 {PATH/TO/kong.conf} + +configuration at {PATH/TO/kong.conf} 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 {kong.conf} --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 the following +supported namespaces will be converted into an equivalent Nginx +directive by removing the prefix and added to the appropriate section of the +Nginx configuration: + +- `nginx_main_`: Injects `` in Kong's configuration + `main` context. +- `nginx_events_`: Injects `` in Kong's `events {}` + block. +- `nginx_http_`: Injects `` in Kong's `http {}` block. +- `nginx_proxy_`: Injects `` in Kong's proxy + `server {}` block. +- `nginx_upstream_`: Injects `` in Kong's proxy + `upstream {}` block. +- `nginx_admin_`: Injects `` in Kong's Admin API + `server {}` block. +- `nginx_status_`: Injects `` in Kong's Status API + `server {}` block (only effective if `status_listen` is enabled). +- `nginx_stream_`: Injects `` in Kong's stream module + `stream {}` block (only effective if `stream_listen` is enabled). +- `nginx_sproxy_`: Injects `` in Kong's stream module + `server {}` block (only effective if `stream_listen` is enabled). +- `nginx_supstream_`: Injects `` in Kong's stream + module `upstream {}` block. + +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; +``` + +If you want to add the same directive multiple times, you can specify it like the following example: + +```bash +export "KONG_NGINX_MAIN_ENV=HTTP_SSO_ENDPOINT;env PROXY_SSO_ENDPOINT" +export HTTP_SSO_ENDPOINT=http://example.com +export PROXY_SSO_ENDPOINT=http://example.com +``` + +This results in Kong injecting this line: + +``` +env HTTP_SSO_ENDPOINT;env PROXY_SSO_ENDPOINT; +``` + +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 [Nginx reference](https://nginx.org/en/docs/beginners_guide.html#conf_structure). + +For a list of Nginx directives, see the [Nginx directives index](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 following Lua functions are available in the [templating engine][pl.template]: + +- `pairs`, `ipairs` +- `tostring` +- `os.getenv` + +The default template for +Kong Gateway can be found by entering the following command on the system +running your Kong instance: `find / -type d -name "templates" | grep kong`. For +open-source Kong Gateway, you can also see the +[templates directory][templates]. + +The template is split in two +Nginx configuration files: `nginx.lua` and `nginx_kong.lua`. The former is +minimal 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 +``` + + +## 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` property. + +**Default:** `logs/error.log` + +--- + +#### proxy_stream_access_log + +Path for tcp streams proxy port 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. + +`basic` is defined as `'$remote_addr [$time_local] ' '$protocol $status +$bytes_sent $bytes_received ' '$session_time'` + +**Default:** `logs/access.log basic` + +--- + +#### proxy_stream_error_log + +Path for tcp streams proxy port request error logs. The granularity of these +logs is adjusted by the `log_level` property. + +**Default:** `logs/error.log` + +--- + +#### admin_access_log + +Path for Admin API request access logs. If Hybrid Mode is enabled and the +current node is set to be the Control Plane, then the connection requests from +Data Planes are also written to this file with server name +"kong_cluster_listener". + +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` property. + +**Default:** `logs/error.log` + +--- + +#### status_access_log + +Path for Status API request access logs. The default value of `off` implies +that logging for this API is disabled by default. + +If this value is a relative path, it will be placed under the `prefix` +location. + +**Default:** `off` + +--- + +#### status_error_log + +Path for Status API request error logs. The granularity of these logs is +adjusted by the `log_level` property. + +**Default:** `logs/status_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` + +--- + +#### pluginserver_names + +Comma-separated list of names for pluginserver processes. The actual names are +used for log messages and to relate the actual settings. + +**Default:** none + +--- + +#### pluginserver_XXX_socket + +Path to the unix socket used by the pluginserver. + +**Default:** `/.socket` + +--- + +#### pluginserver_XXX_start_cmd + +Full command (including any needed arguments) to start the pluginserver + +**Default:** `/usr/local/bin/` + +--- + +#### pluginserver_XXX_query_cmd + +Full command to "query" the pluginserver. Should produce a JSON with the +dump info of all plugins it manages + +**Default:** `/usr/local/bin/query_` + +--- + +#### port_maps + +With this configuration parameter, you can let the Kong to know about the port +from which the packets are forwarded to it. This is fairly common when running +Kong in a containerized or virtualized environment. + +For example, `port_maps=80:8000, 443:8443` instructs Kong that the port 80 is +mapped to 8000 (and the port 443 to 8443), where 8000 and 8443 are the ports +that Kong is listening to. + +This parameter helps Kong set a proper forwarded upstream HTTP request header +or to get the proper forwarded port with the Kong PDK (in case other means +determining it has failed). It changes routing by a destination port to route by +a port from which packets are forwarded to Kong, and similarly it changes the +default plugin log serializer to use the port according to this mapping instead +of reporting the port Kong is listening to. + +**Default:** none + +--- + +#### anonymous_reports + +Send anonymous usage data such as error stack traces to help improve Kong. + +**Default:** `on` + +--- + + +### Hybrid Mode section + +#### role + +Use this setting to enable Hybrid Mode, This allows running some Kong nodes in +a control plane role with a database and have them deliver configuration updates +to other nodes running to DB-less running in a Data Plane role. + +Valid values to this setting are: + +- `traditional`: do not use Hybrid Mode. +- `control_plane`: this node runs in a control plane role. It can use a + database and will deliver configuration updates to data plane nodes. +- `data_plane`: this is a data plane node. It runs DB-less and receives + configuration updates from a control plane node. + +**Default:** `traditional` + +--- + +#### cluster_mtls + +Sets the verification between nodes of the cluster. + +Valid values to this setting are: + +- `shared`: use a shared certificate/key pair specified with the `cluster_cert` + and `cluster_cert_key` settings. Note that CP and DP nodes have to present the + same certificate to establish mTLS connections. +- `pki`: use `cluster_ca_cert`, `cluster_server_name` and `cluster_cert` for + verification. These are different certificates for each DP node, but issued by + a cluster-wide common CA certificate: `cluster_ca_cert`. + +**Default:** `shared` + +--- + +#### cluster_cert + +Filename of the cluster certificate to use when establishing secure +communication between control and data plane nodes. + +You can use the `kong hybrid` command to generate the certificate/key pair. + +Under `shared` mode, it must be the same for all nodes. Under `pki` mode it +should be a different certificate for each DP node. + +**Default:** none + +--- + +#### cluster_cert_key + +Filename of the cluster certificate key to use when establishing secure +communication between control and data plane nodes. + +You can use the `kong hybrid` command to generate the certificate/key pair. + +Under `shared` mode, it must be the same for all nodes. Under `pki` mode it +should be a different certificate for each DP node. + +**Default:** none + +--- + +#### cluster_ca_cert + +The trusted CA certificate file in PEM format used for Control Plane to verify +Data Plane's certificate and Data Plane to verify Control Plane's certificate. + +Required on data plane if `cluster_mtls` is set to `pki`. + +If Control Plane certificate is issued by a well known CA, user can set +`lua_ssl_trusted_certificate=system` on Data Plane and leave this field empty. + +This field is ignored if `cluster_mtls` is set to `shared`. + +**Default:** none + +--- + + +### Hybrid Mode Data Plane section + +#### cluster_server_name + +The server name used in the SNI of the TLS connection from a DP node to a CP +node. + +Must match the Common Name (CN) or Subject Alternative Name (SAN) found in the +CP certificate. + +If `cluster_mtls` is set to `shared`, this setting is ignored and +`kong_clustering` is used. + +**Default:** none + +--- + +#### cluster_control_plane + +To be used by data plane nodes only: address of the control plane node from +which configuration updates will be fetched, in `host:port` format. + +**Default:** none + +--- + +#### cluster_telemetry_endpoint +{:.badge .enterprise} + +To be used by data plane nodes only: telemetry address of the control plane +node to which telemetry updates will be posted in `host:port` format. + +**Default:** none + +--- + +#### cluster_telemetry_server_name +{:.badge .enterprise} + +The SNI (Server Name Indication extension) to use for Vitals telemetry data. + +**Default:** none + +--- + + +### Hybrid Mode Control Plane section + +#### cluster_listen + +Comma-separated list of addresses and ports on which the cluster control plane +server should listen for data plane connections. + +The cluster communication port of the control plane must be accessible by all +the data planes within the same cluster. This port is mTLS protected to ensure +end-to-end security and integrity. + +This setting has no effect if `role` is not set to `control_plane`. + +Connection made to this endpoint are logged to the same location as Admin API +access logs. + +See `admin_access_log` config description for more information. + +**Default:** `0.0.0.0:8005` + +--- + +#### cluster_telemetry_listen +{:.badge .enterprise} + +Comma-separated list of addresses and ports on which the cluster control plane +server should listen for data plane telemetry connections. + +The cluster communication port of the control plane must be accessible by all +the data planes within the same cluster. + +This setting has no effect if `role` is not set to `control_plane`. + +**Default:** `0.0.0.0:8006` + +--- + +#### cluster_data_plane_purge_delay + +How many seconds must pass from the time a DP node becomes offline to the time +its entry gets removed from the database, as returned by the +/clustering/data-planes Admin API endpoint. + +This is to prevent the cluster data plane table from growing indefinitely. The +default is set to 14 days. That is, if CP haven't heard from a DP for 14 days, +its entry will be removed. + +**Default:** `1209600` + +--- + +#### cluster_ocsp + +Whether to check for revocation status of DP certificates using OCSP (Online +Certificate Status Protocol). + +If enabled, the DP certificate should contain the "Certificate Authority +Information Access" extension and the OCSP method with URI of which the OCSP +responder can be reached from CP. + +OCSP checks are only performed on CP nodes, it has no effect on DP nodes. + +Valid values to this setting are: + +- `on`: OCSP revocation check is enabled and DP must pass the check in order to + establish connection with CP. +- `off`: OCSP revocation check is disabled. +- `optional`: OCSP revocation check will be attempted, however, if the required + extension is not found inside DP provided certificate or communication with + the OCSP responder failed, then DP is still allowed through. + +**Default:** `off` + +--- + +#### cluster_max_payload + +This sets the maximum payload size allowed to be sent across from CP to DP in +Hybrid mode. + +Default is 4Mb - 4 * 1024 * 1024 due to historical reasons. + +**Default:** `4194304` + +--- + +### 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. +- `deferred` instructs to use a deferred accept on Linux (the TCP_DEFER_ACCEPT + socket option). +- `bind` instructs to make a separate bind() call for a given address:port + pair. +- `reuseport` instructs to create an individual listening socket for each + worker process allowing the Kernel to better distribute incoming connections + between worker processes +- `backlog=N` sets the maximum length for the queue of pending TCP connections. + This number should not be too small in order to prevent clients seeing + "Connection refused" error connecting to a busy Kong instance. **Note:** on + Linux, this value is limited by the setting of `net.core.somaxconn` Kernel + parameter. In order for the larger `backlog` set here to take effect it is + necessary to raise `net.core.somaxconn` at the same time to match or exceed + the `backlog` number set. + +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 reuseport backlog=16384, 0.0.0.0:8443 http2 ssl reuseport backlog=16384` + +--- + +#### proxy_url + +Kong Proxy URL + +The lookup, or balancer, address for your Kong Proxy nodes. + +This value is commonly used in a microservices or service-mesh oriented +architecture. + +Accepted format (parts in parentheses are optional): + +`://(:(/))` + +Examples: + +- `://:` -> `proxy_url = http://127.0.0.1:8000` +- `SSL ://` -> `proxy_url = https://proxy.domain.tld` +- `:///` -> `proxy_url = http://dev-machine/dev-285` + +By default, Kong Manager, and Dev Portal will use the window request host and +append the resolved listener port depending on the requested protocol. + +**Default:** none + +--- + +#### 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: + +- `ssl` will require that all connections made through a particular + address/port be made with TLS enabled. +- `proxy_protocol` will enable usage of the PROXY protocol for a given + address/port. +- `bind` instructs to make a separate bind() call for a given address:port + pair. +- `reuseport` instructs to create an individual listening socket for each + worker process allowing the Kernel to better distribute incoming connections + between worker processes +- `backlog=N` sets the maximum length for the queue of pending TCP connections. + This number should not be too small in order to prevent clients seeing + "Connection refused" error connecting to a busy Kong instance. **Note:** on + Linux, this value is limited by the setting of `net.core.somaxconn` Kernel + parameter. In order for the larger `backlog` set here to take effect it is + necessary to raise `net.core.somaxconn` at the same time to match or exceed + the `backlog` number set. + +Examples: + +``` +stream_listen = 127.0.0.1:7000 reuseport backlog=16384 +stream_listen = 0.0.0.0:989 reuseport backlog=65536, 0.0.0.0:20 +stream_listen = [::1]:1234 backlog=16384 +``` + +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_api_uri + +Hierarchical part of a URI which is composed optionally of a host, port, and +path at which the Admin API accepts HTTP or HTTPS traffic. When this config is +disabled, Kong Manager will use the window protocol + host and append the +resolved admin_listen HTTP/HTTPS port. + +**Default:** none + +--- + +#### 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. +- `proxy_protocol` will enable usage of the PROXY protocol for a given + address/port. +- `deferred` instructs to use a deferred accept on Linux (the TCP_DEFER_ACCEPT + socket option). +- `bind` instructs to make a separate bind() call for a given address:port + pair. +- `reuseport` instructs to create an individual listening socket for each + worker process allowing the Kernel to better distribute incoming connections + between worker processes +- `backlog=N` sets the maximum length for the queue of pending TCP connections. + This number should not be too small in order to prevent clients seeing + "Connection refused" error connecting to a busy Kong instance. **Note:** on + Linux, this value is limited by the setting of `net.core.somaxconn` Kernel + parameter. In order for the larger `backlog` set here to take effect it is + necessary to raise `net.core.somaxconn` at the same time to match or exceed + the `backlog` number set. + +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: `admin_listen = 127.0.0.1:8444 http2 ssl` + +**Default:** `127.0.0.1:8001 reuseport backlog=16384, 127.0.0.1:8444 http2 ssl reuseport backlog=16384` + +--- + +#### status_listen + +Comma-separated list of addresses and ports on which the Status API should +listen. + +The Status API is a read-only endpoint allowing monitoring tools to retrieve +metrics, healthiness, and other non-sensitive information of the current Kong +node. + +The following suffix can be specified for each pair: + +- `ssl` will require that all connections made through a particular + address/port be made with TLS enabled. + +This value can be set to `off`, disabling the Status API for this node. + +Example: `status_listen = 0.0.0.0:8100` + +**Default:** `off` + +--- + +#### 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` + +**Note**: If the `kong` user and the `kong` group are not available, the +default user and group credentials will be `nobody nobody`. + +**Default:** `kong kong` + +--- + +#### 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 the equivalent Nginx 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 each of the two in-memory caches for database entities. The accepted +units are `k` and `m`, with a minimum recommended value of a few MBs. + +**Note**: As this option controls the size of two different cache entries, the +total memory Kong uses to cache entities might be double this value. + +**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:** `intermediate` + +--- + +#### 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_protocols + +Enables the specified protocols for client-side connections. The set of +supported protocol versions also depends on the version of OpenSSL Kong was +built with. This value is ignored if `ssl_cipher_suite` is not `custom`. + +See http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols + +**Default:** `TLSv1.1 TLSv1.2 TLSv1.3` + +--- + +#### ssl_prefer_server_ciphers + +Specifies that server ciphers should be preferred over client ciphers when +using the SSLv3 and TLS protocols. This value is ignored if `ssl_cipher_suite` +is not `custom`. + +See +http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_prefer_server_ciphers + +**Default:** `on` + +--- + +#### ssl_dhparam + +Defines DH parameters for DHE ciphers from the predefined groups: `ffdhe2048`, +`ffdhe3072`, `ffdhe4096`, `ffdhe6144`, `ffdhe8192`, or from the absolute path to +a parameters file. + +This value is ignored if `ssl_cipher_suite` is `modern` or `intermediate`. The +reason is that `modern` has no ciphers that needs this, and `intermediate` uses +`ffdhe2048`. + +See http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam + +**Default:** none + +--- + +#### ssl_session_tickets + +Enables or disables session resumption through TLS session tickets. This has no +impact when used with TLSv1.3. + +Kong enables this by default for performance reasons, but it has security +implications: https://github.com/mozilla/server-side-tls/issues/135 + +See http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets + +**Default:** `on` + +--- + +#### ssl_session_timeout + +Specifies a time during which a client may reuse the session parameters. See +the rationale: https://github.com/mozilla/server-side-tls/issues/198 + +See http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_timeout + +**Default:** `1d` + +--- + +#### ssl_cert + +Comma-separated list of the absolute path to the certificates for +`proxy_listen` values with TLS enabled. + +If more than one certificates are specified, it can be used to provide +alternate type of certificate (for example, ECC certificate) that will be served +to clients that supports them. Note to properly serve using ECC certificates, it +is recommended to also set `ssl_cipher_suite` to `modern` or `intermediate`. + +Unless this option is explicitly set, Kong will auto-generate a pair of default +certificates (RSA + ECC) first time it starts up and use it for serving TLS +requests. + +**Default:** none + +--- + +#### ssl_cert_key + +Comma-separated list of the absolute path to the keys for `proxy_listen` values +with TLS enabled. + +If more than one certificate was specified for `ssl_cert`, then this option +should contain the corresponding key for all certificates provided in the same +order. + +Unless this option is explicitly set, Kong will auto-generate a pair of default +private keys (RSA + ECC) first time it starts up and use it for serving TLS +requests. + +**Default:** none + +--- + +#### client_ssl + +Determines if Nginx should attempt to send client-side TLS certificates and +perform Mutual TLS Authentication with upstream service when proxying requests. + +**Default:** `off` + +--- + +#### client_ssl_cert + +If `client_ssl` is enabled, the absolute path to the client certificate for the +`proxy_ssl_certificate` directive. + +This value can be overwritten dynamically with the `client_certificate` +attribute of the `Service` object. + +**Default:** none + +--- + +#### client_ssl_cert_key + +If `client_ssl` is enabled, the absolute path to the client TLS key for the +`proxy_ssl_certificate_key` directive. + +This value can be overwritten dynamically with the `client_certificate` +attribute of the `Service` object. + +**Default:** none + +--- + +#### admin_ssl_cert + +Comma-separated list of the absolute path to the certificates for +`admin_listen` values with TLS enabled. + +See docs for `ssl_cert` for detailed usage. + +**Default:** none + +--- + +#### admin_ssl_cert_key + +Comma-separated list of the absolute path to the keys for `admin_listen` values +with TLS enabled. + +See docs for `ssl_cert_key` for detailed usage. + +**Default:** none + +--- + +#### status_ssl_cert + +Comma-separated list of the absolute path to the certificates for +`status_listen` values with TLS enabled. + +See docs for `ssl_cert` for detailed usage. + +**Default:** none + +--- + +#### status_ssl_cert_key + +Comma-separated list of the absolute path to the keys for `status_listen` +values with TLS enabled. + +See docs for `ssl_cert_key` for detailed usage. + +**Default:** none + +--- + +#### 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). +- `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-Response-Latency`: time taken (in millisecond) by Kong to produce a + response in case of e.g. plugin short-circuiting the request, or in in case of + an error. +- `X-Kong-Upstream-Latency`: Time taken (in milliseconds) by the upstream + service to send response headers. +- `X-Kong-Admin-Latency`: Time taken (in milliseconds) by Kong to process an + Admin API request. +- `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 `X-Kong-Proxy-Latency`, + `X-Kong-Response-Latency`, `X-Kong-Admin-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` + +--- + +#### 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` + +--- + +#### upstream_keepalive_pool_size + +Sets the default size of the upstream keepalive connection pools. + +Upstream keepalive connection pools are segmented by the `dst ip/dst port/SNI` +attributes of a connection. + +A value of `0` will disable upstream keepalive connections by default, forcing +each upstream request to open a new connection. + +**Default:** `60` + +--- + +#### upstream_keepalive_max_requests + +Sets the default maximum number of requests than can be proxied upstream +through one keepalive connection. + +After the maximum number of requests is reached, the connection will be closed. + +A value of `0` will disable this behavior, and a keepalive connection can be +used to proxy an indefinite number of requests. + +**Default:** `100` + +--- + +#### upstream_keepalive_idle_timeout + +Sets the default timeout (in seconds) for which an upstream keepalive +connection should be kept open. When the timeout is reached while the connection +has not been reused, it will be closed. + +A value of `0` will disable this behavior, and an idle keepalive connection may +be kept open indefinitely. + +**Default:** `60` + +--- + + +### NGINX Injected Directives section + +Nginx directives can be dynamically injected in the runtime nginx.conf file +without requiring a custom Nginx configuration template. + +All configuration properties respecting the naming scheme +`nginx__` will result in `` being injected in +the Nginx configuration block corresponding to the property's ``. + +Example: `nginx_proxy_large_client_header_buffers = 8 24k` + +Will inject the following directive in Kong's proxy `server {}` block: + +`large_client_header_buffers 8 24k;` + +The following namespaces are supported: + +- `nginx_main_`: Injects `` in Kong's configuration + `main` context. +- `nginx_events_`: Injects `` in Kong's `events {}` + block. +- `nginx_http_`: Injects `` in Kong's `http {}` block. +- `nginx_proxy_`: Injects `` in Kong's proxy `server {}` + block. +- `nginx_upstream_`: Injects `` in Kong's proxy `upstream + {}` block. +- `nginx_admin_`: Injects `` in Kong's Admin API `server + {}` block. +- `nginx_status_`: Injects `` in Kong's Status API + `server {}` block (only effective if `status_listen` is enabled). +- `nginx_stream_`: Injects `` in Kong's stream module + `stream {}` block (only effective if `stream_listen` is enabled). +- `nginx_sproxy_`: Injects `` in Kong's stream module + `server {}` block (only effective if `stream_listen` is enabled). +- `nginx_supstream_`: Injects `` in Kong's stream module + `upstream {}` block. + +As with other configuration properties, Nginx directives can be injected via +environment variables when capitalized and prefixed with `KONG_`. + +Example: `KONG_NGINX_HTTP_SSL_PROTOCOLS` -> `nginx_http_ssl_protocols` + +Will inject the following directive in Kong's `http {}` block: + +`ssl_protocols ;` + +If different sets of protocols are desired between the proxy and Admin API +server, you may specify `nginx_proxy_ssl_protocols` and/or +`nginx_admin_ssl_protocols`, both of which taking precedence over the `http {}` +block. + +--- + +#### nginx_main_worker_rlimit_nofile + +Changes the limit on the maximum number of open files for worker processes. + +The special and default value of `auto` sets this value to `ulimit -n` with the +upper bound limited to 16384 as a measure to protect against excess memory use. + +See http://nginx.org/en/docs/ngx_core_module.html#worker_rlimit_nofile + +**Default:** `auto` + +--- + +#### nginx_events_worker_connections + +Sets the maximum number of simultaneous connections that can be opened by a +worker process. + +The special and default value of `auto` sets this value to `ulimit -n` with the +upper bound limited to 16384 as a measure to protect against excess memory use. + +See http://nginx.org/en/docs/ngx_core_module.html#worker_connections + +**Default:** `auto` + +--- + +#### nginx_http_client_header_buffer_size + +Sets buffer size for reading the client request headers. + +See +http://nginx.org/en/docs/http/ngx_http_core_module.html#client_header_buffer_size + +**Default:** `1k` + +--- + +#### nginx_http_large_client_header_buffers + +Sets the maximum number and size of buffers used for reading large clients +requests headers. + +See +http://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers + +**Default:** `4 8k` + +--- + +#### nginx_http_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 + +**Default:** `0` + +--- + +#### nginx_admin_client_max_body_size + +Defines the maximum request body size for Admin API. + +**Default:** `10m` + +--- + +#### nginx_http_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 + +**Default:** `8k` + +--- + +#### nginx_admin_client_body_buffer_size + +Defines the buffer size for reading the request body on Admin API. + +**Default:** `10m` + +--- + +#### nginx_http_lua_regex_match_limit + +Global `MATCH_LIMIT` for PCRE regex matching. The default of `100000` should +ensure at worst any regex Kong executes could finish within roughly 2 seconds. + +**Default:** `100000` + +--- + + +### Datastore section + +Kong can run with a database to store coordinated data between Kong nodes in a +cluster, or without a database, where each node stores its information +independently in memory. + +When using a database, Kong will store data for all its entities (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. + +When not using a database, Kong is said to be in "DB-less mode": it will keep +its entities in memory, and each node needs to have this data entered via a +declarative configuration file, which can be specified through the +`declarative_config` property, or via the Admin API using the `/config` +endpoint. + +When using PostgreSQL as the backend storage, you can optionally enable Kong to +serve read queries from a separate database instance. + +When the number of proxies is large, this can greatly reduce the load on the +main PostgreSQL instance and achieve better scalability. It may also reduce the +latency jitter if the Kong proxy node's latency to the main PostgreSQL instance is +high. + +The read-only PostgreSQL instance only serves read queries and write queries +still goes to the main connection. The read-only PostgreSQL instance can be +eventually consistent while replicating changes from the main instance. + +At least the `pg_ro_host` config is needed to enable this feature. + +By default, all other database config for the read-only connection are +inherited from the corresponding main connection config described above but may +be optionally overwritten explicitly using the `pg_ro_*` config below. + +--- + +#### database + +Determines which of PostgreSQL or Cassandra this node will use as its +datastore. + +Accepted values are `postgres`, `cassandra`, and `off`. + +**Default:** `postgres` + +--- + + +#### PostgreSQL settings + +name | description | default +-------|--------------|---------- +**pg_host** | Host of the PostgreSQL server. | `127.0.0.1` +**pg_port** | Port of the PostgreSQL server. | `5432` +**pg_timeout** | Defines the timeout (in ms), for connecting, reading and writing. | `5000` +**pg_user** | PostgreSQL user. | `kong` +**pg_password** | PostgreSQL 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. Because PostgreSQL uses the same port for TLS and non-TLS, this is only a hint. If the server does not support TLS, the established connection will be a plain one. | `off` +**pg_ssl_version** | When using ssl between Kong and PostgreSQL, the version of tls to use. Accepted values are `tlsv1`, `tlsv1_2`, or `tlsv1_3`. | `tlsv1` +**pg_ssl_required** | When `pg_ssl` is on this determines if TLS must be used between Kong and PostgreSQL. It aborts the connection if the server does not support SSL connections. | `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` +**pg_ssl_cert** | The absolute path to the PEM encoded client TLS certificate for the PostgreSQL connection. Mutual TLS authentication against PostgreSQL is only enabled if this value is set. | none +**pg_ssl_cert_key** | If `pg_ssl_cert` is set, the absolute path to the PEM encoded client TLS private key for the PostgreSQL connection. | none +**pg_max_concurrent_queries** | Sets the maximum number of concurrent queries that can be executing at any given time. This limit is enforced per worker process; the total number of concurrent queries for this node will be will be: `pg_max_concurrent_queries * nginx_worker_processes`. The default value of 0 removes this concurrency limitation. | `0` +**pg_semaphore_timeout** | Defines the timeout (in ms) after which PostgreSQL query semaphore resource acquisition attempts will fail. Such failures will generally result in the associated proxy or Admin API request failing with an HTTP 500 status code. Detailed discussion of this behavior is available in the online documentation. | `60000` +**pg_keepalive_timeout** | Defines the time in milliseconds that an idle connection to PostreSQL server will be kept alive. | `60000` +**pg_ro_host** | Same as `pg_host`, but for the read-only connection. **Note:** Refer to the documentation section above for detailed usage. | none +**pg_ro_port** | Same as `pg_port`, but for the read-only connection. | `` +**pg_ro_timeout** | Same as `pg_timeout`, but for the read-only connection. | `` +**pg_ro_user** | Same as `pg_user`, but for the read-only connection. | `` +**pg_ro_password** | Same as `pg_password`, but for the read-only connection. | `` +**pg_ro_database** | Same as `pg_database`, but for the read-only connection. | `` +**pg_ro_schema** | Same as `pg_schema`, but for the read-only connection. | `` +**pg_ro_ssl** | Same as `pg_ssl`, but for the read-only connection. | `` +**pg_ro_ssl_required** | Same as `pg_ssl_required`, but for the read-only connection. | `` +**pg_ro_ssl_verify** | Same as `pg_ssl_verify`, but for the read-only connection. | `` +**pg_ro_ssl_version** | Same as `pg_ssl_version`, but for the read-only connection. | `` +**pg_ro_max_concurrent_queries** | Same as `pg_max_concurrent_queries`, but for the read-only connection. Note: read-only concurrency is not shared with the main (read-write) connection. | `` +**pg_ro_semaphore_timeout** | Same as `pg_semaphore_timeout`, but for the read-only connection. | `` +**pg_ro_keepalive_timeout** | Same as `pg_keepalive_timeout`, but for the read-only connection. | `` + +#### 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_write_consistency** | Consistency setting to use when writing to the Cassandra cluster. | `ONE` +**cassandra_read_consistency** | Consistency setting to use when reading from 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_refresh_frequency** | Frequency (in seconds) at which the cluster topology will be checked for new or decommissioned nodes. A value of `0` will disable this check, and the cluster topology will never be refreshed. | `60` +**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` + +#### declarative_config + +The path to the declarative configuration file which holds the specification of +all entities (Routes, Services, Consumers, etc.) to be used when the `database` +is set to `off`. + +Entities are stored in Kong's in-memory cache, so you must ensure that enough +memory is allocated to it via the `mem_cache_size` property. You must also +ensure that items in the cache never expire, which means that `db_cache_ttl` +should preserve its default value of 0. + +If the Hybrid mode `role` is set to `data_plane` and there's no configuration +cache file, this configuration is used before connecting to the Control Plane +node as a user-controlled fallback. + +**Default:** none + +--- + +#### declarative_config_string + +The declarative configuration as a string + +**Default:** none + +--- + + +### 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 you do +not configure `db_cache_neg_ttl`. + +If set to 0 (default), such cached entities or misses never expire. + +**Default:** `0` + +--- + +#### db_cache_neg_ttl + +Time-to-live (in seconds) of a datastore miss (no entity). + +If not specified (default), `db_cache_ttl` value will be used instead. + +If set to 0, misses will never expire. + +**Default:** none + +--- + +#### 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` + +--- + +#### db_cache_warmup_entities + +Entities to be pre-loaded from the datastore into the in-memory cache at Kong +start-up. + +This speeds up the first access of endpoints that use the given entities. + +When the `services` entity is configured for warmup, the DNS entries for values +in its `host` attribute are pre-resolved asynchronously as well. + +Cache size set in `mem_cache_size` should be set to a value large enough to +hold all instances of the specified entities. + +If the size is insufficient, Kong will log a warning. + +**Default:** `services` + +--- + + +### 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 load balance 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` + +--- + + +### Tuning & Behavior section + +#### worker_consistency + +Defines whether this node should rebuild its state synchronously or +asynchronously (the balancers and the router are rebuilt on updates that affects +them, e.g., updates to Routes, Services or Upstreams, via the Admin API or +loading a declarative configuration file). + +Accepted values are: + +- `strict`: the router will be rebuilt synchronously, causing incoming requests + to be delayed until the rebuild is finished. +- `eventual`: the router will be rebuilt asynchronously via a recurring + background job running every second inside of each worker. + +Note that `strict` ensures that all workers of a given node will always proxy +requests with an identical router, but that increased long tail latency can be +observed if frequent Routes and Services updates are expected. + +Using `eventual` will help preventing long tail latency issues in such cases, +but may cause workers to route requests differently for a short period of time +after Routes and Services updates. + +**Default:** `strict` + +--- + +#### worker_state_update_frequency + +Defines how often the worker state changes are checked with a background job. +When a change is detected, a new router or balancer will be built, as needed. +Raising this value will decrease the load on database servers and result in less +jitter in proxy latency, but it might take more time to propagate changes to +each individual worker. + +**Default:** `5` + +--- + + +### 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 + +Comma-separated list of paths to certificate authority files for Lua cosockets +in PEM format. + +The special value `system` attempts to search for the "usual default" provided +by each distro, according to an arbitrary heuristic. In the current +implementation, The following pathnames will be tested in order, and the first +one found will be used: + +- /etc/ssl/certs/ca-certificates.crt (Debian/Ubuntu/Gentoo) +- /etc/pki/tls/certs/ca-bundle.crt (Fedora/RHEL 6) +- /etc/ssl/ca-bundle.pem (OpenSUSE) +- /etc/pki/tls/cacert.pem (OpenELEC) +- /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem (CentOS/RHEL 7) +- /etc/ssl/cert.pem (OpenBSD, Alpine) + +If no file is found on any of these paths, an error will be raised. + +`system` can be used by itself or in conjunction with other CA filepaths. + +When `pg_ssl_verify` or `cassandra_ssl_verify` are enabled, these certificate +authority files will be used for verifying Kong's database connections. + +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. + +If the maximum depth is reached before reaching the end of the chain, +verification will fail. This helps mitigate certificate based DoS attacks. + +See https://github.com/openresty/lua-nginx-module#lua_ssl_verify_depth + +**Default:** `1` + +--- + +#### lua_ssl_protocols + +Defines the TLS versions supported when handshaking with OpenResty's TCP +cosocket APIs. + +This affects connections made by Lua code, such as connections to the database +Kong uses, or when sending logs using a logging plugin. It does *not* affect +connections made to the upstream Service or from downstream clients. + +**Default:** `TLSv1.1 TLSv1.2 TLSv1.3` + +--- + +#### 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` + +--- + +#### enforce_rbac +{:.badge .enterprise} + +Specifies whether Admin API RBAC is enforced. + +Accepts one of `entity`, `both`, `on`, or `off`. + +- `on`: only endpoint-level authorization is enforced. +- `entity`: entity-level authorization applies. +- `both`: enables both endpoint and entity-level authorization. +- `off`: disables both endpoint and entity-level authorization. + +When enabled, Kong will deny requests to the Admin API when a nonexistent or +invalid RBAC authorization token is passed, or the RBAC user with which the +token is associated does not have permissions to access/modify the requested +resource. + +**Default:** `off` + +--- + +#### rbac_auth_header +{:.badge .enterprise} + +Defines the name of the HTTP request header from which the Admin API will +attempt to authenticate the RBAC user. + +**Default:** `Kong-Admin-Token` + +--- + +#### event_hooks_enabled +{:.badge .enterprise} + +When enabled, event hook entities represent a relationship between an event +(source and event) and an action (handler). Similar to web hooks, event hooks +can be used to communicate Kong Gateway service events. When a particular event +happens on a service, the event hook calls a URL with information about that +event. Event hook configurations differ depending on the handler. The events +that are triggered send associated data. + +See: https://docs.konghq.com/gateway/latest/admin-api/event-hooks/reference/ + +**Default:** `on` + +--- + + +### Kong Manager section + +The Admin GUI for Kong Enterprise. + +--- + +#### admin_gui_listen +{:.badge .free} + +Kong Manager Listeners + +Comma-separated list of addresses and ports on which Kong will expose Kong +Manager. This web application lets you configure and manage Kong, and therefore +should be kept secured. + +Suffixes can be specified for each pair, similarly to the `admin_listen` +directive. + +**Default:** `0.0.0.0:8002, 0.0.0.0:8445 ssl` + +--- + +#### admin_gui_url +{:.badge .free} + +Kong Manager URL + +The lookup, or balancer, address for Kong Manager. + +Accepted format (items in parentheses are optional): + +`://(:(/))` + +Examples: + +- `http://127.0.0.1:8003` +- `https://kong-admin.test` +- `http://dev-machine/dev-285` + +By default, Kong Manager will use the window request host and append the +resolved listener port depending on the requested protocol. + +**Default:** none + +--- + +#### admin_gui_ssl_cert +{:.badge .free} + +The absolute path to the SSL certificate for `admin_gui_listen` values with SSL +enabled. + +**Default:** none + +--- + +#### admin_gui_ssl_cert_key +{:.badge .free} + +The absolute path to the SSL key for `admin_gui_listen` values with SSL +enabled. + +**Default:** none + +--- + +#### admin_gui_flags +{:.badge .free} + +Alters the layout Admin GUI (JSON) The only supported value is `{ +"IMMUNITY_ENABLED": true }` to enable Kong Immunity in the Admin GUI. + +**Default:** `{}` + +--- + +#### admin_gui_access_log +{:.badge .free} + +Kong Manager Access Logs + +Here you can set an absolute or relative path for Kong Manager access logs. +When the path is relative, logs are placed in the `prefix` location. + +Setting this value to `off` disables access logs for Kong Manager. + +**Default:** `logs/admin_gui_access.log` + +--- + +#### admin_gui_error_log +{:.badge .free} + +Kong Manager Error Logs + +Here you can set an absolute or relative path for Kong Manager access logs. +When the path is relative, logs are placed in the `prefix` location. + +Setting this value to `off` disables error logs for Kong Manager. + +Granularity can be adjusted through the `log_level` directive. + +**Default:** `logs/admin_gui_error.log` + +--- + +#### admin_gui_auth +{:.badge .enterprise} + +Kong Manager Authentication Plugin Name + +Secures access to Kong Manager by specifying an authentication plugin to use. + +Supported Plugins: + +- `basic-auth`: Basic Authentication plugin +- `ldap-auth-advanced`: LDAP Authentication plugin +- `openid-connect`: OpenID Connect Authentication plugin + +**Default:** none + +--- + +#### admin_gui_auth_conf +{:.badge .enterprise} + +Kong Manager Authentication Plugin Config (JSON) + +Specifies the configuration for the authentication plugin specified in +`admin_gui_auth`. + +For information about Plugin Configuration consult the associated plugin +documentation. + +Example for `basic-auth`: + +`admin_gui_auth_conf = { "hide_credentials": true }` + +**Default:** none + +--- + +#### admin_gui_auth_password_complexity +{:.badge .enterprise} + +Kong Manager Authentication Password Complexity (JSON) + +When `admin_gui_auth = basic-auth`, this property defines the rules required +for Kong Manager passwords. Choose from preset rules or write your own. + +Example using preset rules: + +`admin_gui_auth_password_complexity = { "kong-preset": "min_8" }` + +All values for kong-preset require the password to contain characters from at +least three of the following categories: + +1. Uppercase characters (A through Z) + +2. Lowercase characters (a through z) + +3. Base-10 digits (0 through 9) + +4. Special characters (for example, &, $, #, %) + +Supported preset rules: + +- `min_8`: minimum length of 8 +- `min_12`: minimum length of 12 +- `min_20`: minimum length of 20 + +To write your own rules, see +https://manpages.debian.org/jessie/passwdqc/passwdqc.conf.5.en.html. + +NOTE: Only keywords "min", "max" and "passphrase" are supported. + +Example: + +`admin_gui_auth_password_complexity = { "min": "disabled,24,11,9,8" }` + +**Default:** none + +--- + +#### admin_gui_session_conf +{:.badge .enterprise} + +Kong Manager Session Config (JSON) + +Specifies the configuration for the Session plugin as used by Kong Manager. + +For information about plugin configuration, consult the Kong Session plugin +documentation. + +Example: + +``` +admin_gui_session_conf = { "cookie_name": "kookie", \ + "secret": "changeme" } +``` + +**Default:** none + +--- + +#### admin_gui_auth_header +{:.badge .enterprise} + +Defines the name of the HTTP request header from which the Admin API will +attempt to identify the Kong Admin user. + +**Default:** `Kong-Admin-User` + +--- + +#### admin_gui_auth_login_attempts +{:.badge .enterprise} + +Number of times a user can attempt to login to Kong Manager. 0 means infinite +attempts allowed. + +**Default:** `0` + +--- + +#### admin_gui_header_txt +{:.badge .free} + +Sets custom text for the Kong Manager header banner. + +Accepts any string. The header banner is not shown if this config entry is +empty. + +**Default:** none + +--- + +#### admin_gui_header_bg_color +{:.badge .free} + +Sets the background color for the Kong Manager header banner. Accepts CSS color +keyword, #-hexadecimal, or RGB format. Invalid values are ignored by Manager. + +**Default:** none + +--- + +#### admin_gui_header_txt_color +{:.badge .free} + +Sets the text color for the Kong Manager header banner. Accepts CSS color +keyword, #-hexadecimal, or RGB format. Invalid values are ignored by Manager. + +**Default:** none + +--- + +#### admin_gui_footer_txt +{:.badge .free} + +Sets custom text for Kong Manager footer banner. + +Accepts any string. The footer banner is not shown if this config entry is +empty. + +**Default:** none + +--- + +#### admin_gui_footer_bg_color +{:.badge .free} + +Sets the background color for the Kong Manager footer banner. Accepts CSS color +keyword, #-hexadecimal, or RGB format. Invalid values are ignored by Manager. + +**Default:** none + +--- + +#### admin_gui_footer_txt_color +{:.badge .free} + +Sets the text color for the Kong Manager footer banner. Accepts CSS color +keyword, #-hexadecimal, or RGB format. Invalid values are ignored by Manager. + +**Default:** none + +--- + +#### admin_gui_login_banner_title +{:.badge .free} + +Sets custom title text for the Kong Manager login banner. Accepts any string. + +The login banner is not shown if both `admin_gui_login_banner_title` and +`admin_gui_login_banner_body` are empty. + +**Default:** none + +--- + +#### admin_gui_login_banner_body +{:.badge .free} + +Sets custom body text for the Kong Manager login banner. Accepts any string. + +The login banner is not shown if both `admin_gui_login_banner_title` and +`admin_gui_login_banner_body` are empty. + +**Default:** none + +--- + + +### Vitals section + +#### vitals +{:.badge .enterprise} + +When enabled, Kong will store and report metrics about its performance. + +When running Kong in a multi-node setup, `vitals` entails two separate meanings +depending on the node. + +On a Proxy-only node, `vitals` determines whether to collect data for Vitals. + +On an Admin-only node, `vitals` determines whether to display Vitals metrics +and visualizations on the dashboard. + +**Default:** `on` + +--- + +#### vitals_strategy +{:.badge .enterprise} + +Determines whether to use the Kong database (either PostgreSQL or Cassandra, as +defined by the `database` config value above), or a separate storage engine, for +Vitals metrics. + +Accepted values are `database`, `prometheus`, or `influxdb`. + +**Default:** `database` + +--- + +#### vitals_tsdb_address +{:.badge .enterprise} + +Defines the host and port of the TSDB server to which Vitals data is written +and read. + +This value is only applied when the `vitals_strategy` option is set to +`prometheus` or `influxdb`. This value accepts IPv4, IPv6, and hostname values. + +If the `vitals_strategy` is set to `prometheus`, this value determines the +address of the Prometheus server from which Vitals data will be read. For +`influxdb` strategies, this value controls both the read and write source for +Vitals data. + +**Default:** none + +--- + +#### vitals_tsdb_user +{:.badge .enterprise} + +Influxdb user + +**Default:** none + +--- + +#### vitals_tsdb_password +{:.badge .enterprise} + +Influxdb password + +**Default:** none + +--- + +#### vitals_statsd_address +{:.badge .enterprise} + +Defines the host and port (and an optional protocol) of the StatsD server to +which Kong should write Vitals metrics. This value is only applied when the +`vitals_strategy` is set to `prometheus`. This value accepts IPv4, IPv6, and, +hostnames. Additionally, the suffix `tcp` can be specified; doing so will result +in Kong sending StatsD metrics via TCP instead of the UDP (default). + +**Default:** none + +--- + +#### vitals_statsd_prefix +{:.badge .enterprise} + +Defines the prefix value attached to all Vitals StatsD events. This prefix is +useful when writing metrics to a multi-tenant StatsD exporter or server. + +**Default:** `kong` + +--- + +#### vitals_statsd_udp_packet_size +{:.badge .enterprise} + +Defines the maximum buffer size in which Vitals statsd metrics will be held and +sent in batches. + +This value is defined in bytes. + +**Default:** `1024` + +--- + +#### vitals_prometheus_scrape_interval +{:.badge .enterprise} + +Defines the scrape_interval query parameter sent to the Prometheus server when +reading Vitals data. + +This should be same as the scrape interval (in seconds) of the Prometheus +server. + +**Default:** `5` + +--- + + +### Developer Portal section + +#### portal +{:.badge .enterprise} + +Developer Portal on/off switch. + +When enabled, Kong exposes the Dev Portal interface and read-only APIs on the +`portal_gui_listen` address, and endpoints on the Admin API to manage assets. + +When enabled along with `portal_auth`, Kong exposes management endpoints for +developer accounts on the Admin API and the Dev Portal API. + +**Default:** `off` + +--- + +#### portal_gui_listen +{:.badge .enterprise} + +Developer Portal GUI listeners. + +Comma-separated list of addresses on which Kong exposes the Developer Portal +GUI. Suffixes can be specified for each pair, similar to the `admin_listen` +directive. + +**Default:** `0.0.0.0:8003, 0.0.0.0:8446 ssl` + +--- + +#### portal_gui_protocol +{:.badge .enterprise} + +Developer Portal GUI protocol. + +The protocol used in conjunction with `portal_gui_host` to construct the +lookup, or balancer address, for your Kong Proxy nodes. + +Examples: `http`,`https` + +**Default:** `http` + +--- + +#### portal_gui_host +{:.badge .enterprise} + +Developer Portal GUI host. + +The host used in conjunction with `portal_gui_protocol` to construct the +lookup, or balancer address, for your Kong Proxy nodes. + +Examples: + +- `:` -> `portal_gui_host = 127.0.0.1:8003` +- `` -> `portal_gui_host = portal_api.domain.tld` + +**Default:** `127.0.0.1:8003` + +--- + +#### portal_cors_origins +{:.badge .enterprise} + +Developer Portal CORS origins. + +A comma separated list of allowed domains for `Access-Control-Allow-Origin` +header. This can be used to resolve CORS issues in custom networking +environments. + +Examples: + +- list of domains: `portal_cors_origins = http://localhost:8003, + https://localhost:8004` +- single domain: `portal_cors_origins = http://localhost:8003` +- all domains: `portal_cors_origins = *` + +NOTE: In most cases, the Developer Portal is able to derive valid CORS origins +by using `portal_gui_protocol`, `portal_gui_host`, and if applicable, +`portal_gui_use_subdomains`. In these cases, `portal_cors_origins` is not needed +and can remain unset. + +**Default:** none + +--- + +#### portal_gui_use_subdomains +{:.badge .enterprise} + +Developer Portal GUI subdomain toggle. + +By default, Dev Portal uses the first namespace in the request path to +determine workspace. By turning `portal_gui_subdomains` on, Dev Portal will +expect a workspace to be included in the request URL as a subdomain. + +Example (off): - `:////` -> +`http://kong-portal.com/example-workspace/index` + +Example (on): - `://.` -> +`http://example-workspace.kong-portal.com/index` + +**Default:** `off` + +--- + +#### portal_gui_ssl_cert +{:.badge .enterprise} + +Developer Portal GUI SSL certificate. + +The absolute path to the SSL certificate for `portal_gui_listen` values with +SSL enabled. + +**Default:** none + +--- + +#### portal_gui_ssl_cert_key +{:.badge .enterprise} + +Developer Portal GUI SSL certificate key. + +The absolute path to the SSL key for `portal_gui_listen` values with SSL +enabled. + +**Default:** none + +--- + +#### portal_gui_access_log +{:.badge .enterprise} + +Developer Portal GUI access log location. + +An absolute or relative path for your Portal GUI access logs. + +Setting this value to `off` disables logging Portal GUI access logs. + +When using relative pathing, logs will be placed under the `prefix` location. + +**Default:** `logs/portal_gui_access.log` + +--- + +#### portal_gui_error_log +{:.badge .enterprise} + +Developer Portal GUI error log location. + +An absolute or relative path for your Portal GUI error logs. + +Setting this value to `off` disables logging Portal GUI error logs. + +When using relative pathing, logs will be placed under the `prefix` location. + +Granularity can be adjusted through the `log_level` directive. + +**Default:** `logs/portal_gui_error.log` + +--- + +#### portal_api_listen +{:.badge .enterprise} + +Developer Portal API listeners. + +Comma-separated list of addresses on which Kong exposes the Developer Portal +API. Suffixes can be specified for each pair, similarly to the `admin_listen` +directive. + +**Default:** `0.0.0.0:8004, 0.0.0.0:8447 ssl` + +--- + +#### portal_api_url +{:.badge .enterprise} + +Developer Portal API URL. + +The lookup, or balancer, address for your Developer Portal nodes. + +This value is commonly used in a microservices or service-mesh oriented +architecture. + +`portal_api_url` is the address on which your Kong Dev Portal API is accessible +by Kong. You should only set this value if your Kong Dev Portal API lives on a +different node than your Kong Proxy. + +Accepted format (parts in parentheses are optional): + +`://(:(/))` + +Examples: + +- `://:` -> `portal_api_url = http://127.0.0.1:8003` +- `SSL ://` -> `portal_api_url = + https://portal_api.domain.tld` +- `:///` -> `portal_api_url = + http://dev-machine/dev-285` + +By default this value points to the local interface: + +- `http://0.0.0.0:8004` + +**Default:** none + +--- + +#### portal_api_ssl_cert +{:.badge .enterprise} + +Developer Portal API SSL certificate. + +The absolute path to the SSL certificate for `portal_api_listen` values with +SSL enabled. + +**Default:** none + +--- + +#### portal_api_ssl_cert_key +{:.badge .enterprise} + +Developer Portal API SSL certificate key. + +The absolute path to the SSL key for `portal_api_listen` values with SSL +enabled. + +**Default:** none + +--- + +#### portal_api_access_log +{:.badge .enterprise} + +Developer Portal API access log location. + +An absolute or relative path for your Portal API access logs. + +Setting this value to `off` disables logging Portal API access logs. + +When using relative pathing, logs will be placed under the `prefix` location. + +**Default:** `logs/portal_api_access.log` + +--- + +#### portal_api_error_log +{:.badge .enterprise} + +Developer Portal API error log location. + +An absolute or relative path for your Portal API error logs. + +Setting this value to `off` disables logging Portal API error logs. + +When using relative pathing, logs will be placed under the `prefix` location. + +Granularity can be adjusted through the `log_level` directive. + +**Default:** `logs/portal_api_error.log` + +--- + +#### portal_is_legacy +{:.badge .enterprise} + +Developer Portal legacy support. + +You can set this value to `on` or `off`. + +* `on`: causes all new portals to render using the legacy rendering system by +default. + +* `off`: causes all new portals to render using the current rendering system. + +**Default:** `off` + +--- + +#### portal_app_auth +{:.badge .enterprise} + +Developer Portal application registration auth provider and strategy. Must be +set to enable the `application-registration` plugin. + +Accepts `kong-oauth2` or `external-oauth2`. + +**Default:** `kong-oauth2` + +--- + + +### Default Developer Portal Authentication section + +Referenced on workspace creation to set Dev Portal authentication defaults in +the database for that particular workspace. + +--- + +#### portal_auth +{:.badge .enterprise} + +Developer Portal authentication plugin name. + +Specifies the authentication plugin to apply to your Developer Portal. +Developers will use the specified form of authentication to request access, +register, and login to your Developer Portal. + +Supported Plugins: + +- Basic Authentication: `portal_auth = basic-auth` +- OIDC Authentication: `portal_auth = openid-connect` + +**Default:** none + +--- + +#### portal_auth_password_complexity +{:.badge .enterprise} + +Dev Portal authentication password complexity, in JSON format. + +When `portal_auth = basic-auth`, this property defines the rules required for +Dev Portal passwords. Choose from preset rules or write your own. + +Example using preset rules: + +`portal_auth_password_complexity = { "kong-preset": "min_8" }` + +All values for kong-preset require the password to contain characters from at +least three of the following categories: + +1. Uppercase characters (A through Z) + +2. Lowercase characters (a through z) + +3. Base-10 digits (0 through 9) + +4. Special characters (for example, &, $, #, %) + +Supported preset rules: + +- `min_8`: minimum length of 8 +- `min_12`: minimum length of 12 +- `min_20`: minimum length of 20 + +To write your own rules, see +https://manpages.debian.org/jessie/passwdqc/passwdqc.conf.5.en.html. + +NOTE: Only keywords "min", "max" and "passphrase" are supported. + +Example: + +`portal_auth_password_complexity = { "min": "disabled,24,11,9,8" }` + +**Default:** none + +--- + +#### portal_auth_conf +{:.badge .enterprise} + +Developer Portal Authentication Plugin Config (JSON) + +Specifies the plugin configuration object in JSON format to be applied to your +Developer Portal authentication. + +For information about Plugin Configuration consult the associated plugin +documentation. + +Example for `basic-auth`: + +`portal_auth_conf = { "hide_credentials": true }` + +**Default:** none + +--- + +#### portal_auth_login_attempts +{:.badge .enterprise} + +Number of times a user can attempt to login to the Dev Portal before password +must be reset. + +0 (default) means infinite attempts allowed. + +Note: Any value greater than 0 will only affect Dev Portals secured with +basic-auth. + +**Default:** `0` + +--- + +#### portal_session_conf +{:.badge .enterprise} + +Portal Session Config (JSON) + +Specifies the configuration for the Session plugin as used by Dev Portal. + +For information about Plugin Configuration consult the Kong Session Plugin +documentation. + +Example: + +``` +portal_session_conf = { "cookie_name": "portal_session", \ + "secret": "changeme", \ + "storage": "kong" } +``` + +**Default:** none + +--- + +#### portal_auto_approve +{:.badge .enterprise} + +Developer Portal Auto Approve Access + +When this flag is set to `on`, a developer will automatically be marked as +"approved" after completing registration. Access can still be revoked through +the Admin GUI or API. + +**Default:** `off` + +--- + +#### portal_token_exp +{:.badge .enterprise} + +Duration in seconds for the expiration of portal login reset/account validation +token. + +**Default:** `21600` + +--- + +#### portal_email_verification +{:.badge .enterprise} + +Portal Developer Email Verification. + +When enabled Developers will receive an email upon registration to verify their +account. Developers will not be able to use the Developer Portal until they +verify their account. + +Note: SMTP must be turned on in order to use this feature. + +**Default:** `off` + +--- + + +### Default Portal Smtp Configuration section + +Referenced on workspace creation to set SMTP defaults in the database for that +particular workspace. + +--- + +#### portal_invite_email +{:.badge .enterprise} + +Enable or disable portal_invite_email + +**Default:** `on` + +--- + +#### portal_access_request_email +{:.badge .enterprise} + +Enable or disable portal_access_request_email + +**Default:** `on` + +--- + +#### portal_approved_email +{:.badge .enterprise} + +Enable or disable portal_approved_email + +**Default:** `on` + +--- + +#### portal_reset_email +{:.badge .enterprise} + +Enable or disable portal_reset_email + +**Default:** `on` + +--- + +#### portal_reset_success_email +{:.badge .enterprise} + +Enable or disable portal_reset_success_email + +**Default:** `on` + +--- + +#### portal_emails_from +{:.badge .enterprise} + +The name and email address for the `From` header for portal emails + +Example: `portal_emails_from = Your Name ` + +Note: Some SMTP servers will not use this value, but instead insert the email +and name associated with the account. + +**Default:** none + +--- + +#### portal_emails_reply_to +{:.badge .enterprise} + +Email address for the `Reply-To` header for portal emails + +Example: `portal_emails_reply_to = example@example.com` + +Note: Some SMTP servers will not use this value, but instead insert the email +associated with the account. + +**Default:** none + +--- + + +### Admin Smtp Configuration section + +#### admin_emails_from +{:.badge .enterprise} + +The email address for the `From` header for admin emails. + +**Default:** `""` + +--- + +#### admin_emails_reply_to +{:.badge .enterprise} + +Email address for the `Reply-To` header for admin emails. + +**Default:** none + +--- + +#### admin_invitation_expiry +{:.badge .enterprise} + +Expiration time for the admin invitation link (in seconds). 0 means no +expiration. + +Example, 72 hours: `72 * 60 * 60 = 259200` + +**Default:** `259200` + +--- + + +### General Smtp Configuration section + +#### smtp_mock +{:.badge .enterprise} + +This flag will mock the sending of emails. This can be used for testing before +the SMTP client is fully configured. + +**Default:** `on` + +--- + +#### smtp_host +{:.badge .enterprise} + +The hostname of the SMTP server to connect to. + +**Default:** `localhost` + +--- + +#### smtp_port +{:.badge .enterprise} + +The port number on the SMTP server to connect to. + +**Default:** `25` + +--- + +#### smtp_starttls +{:.badge .enterprise} + +When set to `on`, STARTTLS is used to encrypt communication with the SMTP +server. This is normally used in conjunction with port 587. + +**Default:** `off` + +--- + +#### smtp_username +{:.badge .enterprise} + +Username used for authentication with SMTP server + +**Default:** none + +--- + +#### smtp_password +{:.badge .enterprise} + +Password used for authentication with SMTP server + +**Default:** none + +--- + +#### smtp_ssl +{:.badge .enterprise} + +When set to `on`, SMTPS is used to encrypt communication with the SMTP server. +This is normally used in conjunction with port 465. + +**Default:** `off` + +--- + +#### smtp_auth_type +{:.badge .enterprise} + +The method used to authenticate with the SMTP server Valid options are `plain`, +`login`, or `nil` + +**Default:** none + +--- + +#### smtp_domain +{:.badge .enterprise} + +The domain used in the `EHLO` connection and part of the `Message-ID` header + +**Default:** `localhost.localdomain` + +--- + +#### smtp_timeout_connect +{:.badge .enterprise} + +The timeout (in milliseconds) for connecting to the SMTP server. + +**Default:** `60000` + +--- + +#### smtp_timeout_send +{:.badge .enterprise} + +The timeout (in milliseconds) for sending data to the SMTP server. + +**Default:** `60000` + +--- + +#### smtp_timeout_read +{:.badge .enterprise} + +The timeout (in milliseconds) for reading data from the SMTP server. + +**Default:** `60000` + +--- + +#### smtp_admin_emails +{:.badge .enterprise} + +Comma separated list of admin emails to receive notifications. + +Example `admin1@example.com, admin2@example.com` + +**Default:** none + +--- + + +### Data & Admin Audit section + +When enabled, Kong will store detailed audit data regarding Admin API and +database access. In most cases, updates to the database are associated with +Admin API requests. As such, database object audit log data is tied to a given +HTTP via a unique identifier, providing built-in association of Admin API and +database traffic. + +--- + +#### audit_log + +When enabled, Kong will log information about Admin API access and database row +insertions, updates, and deletes. + +**Default:** `off` + +--- + +#### audit_log_ignore_methods + +Comma-separated list of HTTP methods that will not generate audit log entries. +By default, all HTTP requests will be logged. + +**Default:** none + +--- + +#### audit_log_ignore_paths + +Comma-separated list of request paths that will not generate audit log entries. +By default, all HTTP requests will be logged. + +**Default:** none + +--- + +#### audit_log_ignore_tables + +Comma-separated list of database tables that will not generate audit log +entries. By default, updates to all database tables will be logged (the term +"updates" refers to the creation, update, or deletion of a row). + +**Default:** none + +--- + +#### audit_log_payload_exclude + +Comma-separated list of keys that will be filtered out of the payload. Keys +that were filtered will be recorded in the audit log. + +**Default:** `token, secret, password` + +--- + +#### audit_log_record_ttl + +Length, in seconds, of the TTL for audit log records. Records in the database +older than their TTL are automatically purged. + +Example, 30 days: `30 * 24 * 60 * 60 = 2592000` + +**Default:** `2592000` + +--- + +#### audit_log_signing_key + +Defines the path to a private RSA signing key that can be used to insert a +signature of audit records, adjacent to the record. The corresponding public key +should be stored offline, and can be used the validate audit entries in the +future. If this value is undefined, no signature will be generated. + +**Default:** none + +--- + + +### Granular Tracing section + +Granular tracing offers a mechanism to expose metrics and detailed debug data +about the lifecycle of Kong in a human- or machine-consumable format. + +--- + +#### tracing +{:.badge .enterprise} + +When enabled, Kong will generate granular debug data about various portions of +the request lifecycle, such as DB or DNS queries, plugin execution, core handler +timing, etc. + +**Default:** `off` + +--- + +#### tracing_write_strategy +{:.badge .enterprise} + +Defines how Kong will write tracing data at the conclusion of the request. The +default option, `file`, writes a human-readable depiction of tracing data to a +configurable location on the node's file system. Other strategies write tracing +data as a JSON document to the configured endpoint. Valid entries for this +option are `file`, `file_raw`, `http`, `tcp`, `tls`, and `udp`. + +**Default:** `file` + +--- + +#### tracing_write_endpoint +{:.badge .enterprise} + +Defines the endpoint to which tracing data will be written. + +- For the `file` and `file_raw` tracing write strategies, this value must be a + valid location on the node's file system to which Kong must have write access. +- For the `tcp`, `tls`, and `udp` strategies, this value is defined as a string + in the form of: `:` +- For the `http` strategy, this value is defined in the form of: + `://(:(/))` + +Traces sent via HTTP are delivered via POST method with an `application/json` +Content-Type. + +**Default:** none + +--- + +#### tracing_time_threshold +{:.badge .enterprise} + +The minimum time, in microseconds, over which a trace must execute in order to +write the trace data to the configured endpoint. This configuration can be used +to lower the noise present in trace data by removing trace objects that are not +interesting from a timing perspective. The default value of `0` removes this +limitation, causing traces of any duration to be written. + +**Default:** `0` + +--- + +#### tracing_types +{:.badge .enterprise} + +Defines the types of traces that are written. + +Trace types not defined in this list are ignored, regardless of their lifetime. +The default special value of `all` results in all trace types being written, +regardless of type. + +The following trace types are included: + +- `query`: trace the database query +- `legacy_query`: (deprecated) trace the database query with legacy DAO +- `router`: trace Kong routing the request; internal routing time +- `balancer`: trace the execution of the overall balancer phase +- `balancer.getPeer`: trace Kong selecting an upstream peer from the + ring-balancer +- `balancer.toip`: trace balancer to resolve peer's host to IP +- `connect.toip`: trace cosocket to resolve target's host to IP +- `access.before`: trace the preprocessing of access phase, like parameter + parsing, route matching, and balance preparation +- `access.after`: trace the postprocess of access phase, like balancer + execution and internal variable assigning +- `cassandra_iterate`: trace Cassandra driver to paginate over results +- `plugin`: trace plugins phase handlers + +**Default:** `all` + +--- + +#### tracing_debug_header +{:.badge .enterprise} + +Defines the name of the HTTP request header that must be present in order to +generate traces within a request. Setting this value provides a mechanism to +selectively generate request traces at the client's request. Note that the value +of the header does not matter, only that the header is present in the request. +When this value is not set and tracing is enabled, Kong will generate trace data +for all requests flowing through the proxy and Admin API. Note that data from +certificate handling phases is not logged when this setting is enabled. + +**Default:** none + +--- + +#### generate_trace_details +{:.badge .enterprise} + +When enabled, Kong will write context- specific details into traces. Trace +details offer more data about the context of the trace. This can significantly +increase the size of trace reports. Note also that trace details may contain +potentially sensitive information, such as raw SQL queries; care should be taken +to store traces properly when this option is enabled. + +**Default:** `off` + +--- + + +### Route Collision Detection/Prevention section + +#### route_validation_strategy +{:.badge .enterprise} + +The strategy used to validate routes when creating or updating them. + +Different strategies are available to tune how to enforce splitting traffic of +workspaces. + +- `smart` is the default option and uses the algorithm described in + https://docs.konghq.com/gateway/latest/kong-enterprise/workspaces/ +- `off` disables any check +- `path` enforces routes to comply with the pattern described in config + enforce_route_path_pattern + +**Default:** `smart` + +--- + +#### enforce_route_path_pattern +{:.badge .enterprise} + +Specifies the Lua pattern which will be enforced on the `paths` attribute of a +Route object. You can also add a placeholder for the workspace in the pattern, +which will be rendered during runtime based on the workspace to which the +`route` belongs. + +This setting is only relevant if `route_validation_strategy` is set to `path`. + +Example For Pattern `/$(workspace)/v%d/.*` valid paths are: + +1. `/group1/v1/` if route belongs to workspace `group1`. + +2. `/group2/v1/some_path` if route belongs to workspace `group2`. + +**Default:** none + +--- + + +### Database Encryption & Keyring Management section + +When enabled, Kong will transparently encrypt sensitive fields, such as +Consumer credentials, TLS private keys, and RBAC user tokens, among others. A +full list of encrypted fields is available from the Kong Enterprise +documentation site. + +Encrypted data is transparently decrypted before being displayed to the Admin +API or made available to plugins or core routing logic. + +While this feature is GA, do note that we currently do not provide normal +semantic versioning compatibility guarantees on the keyring feature's APIs in +that Kong may make a breaking change to the feature in a minor version. Also +note that mis-management of keyring data may result in irrecoverable data loss. + +--- + +#### keyring_enabled +{:.badge .enterprise} + +When enabled, Kong will encrypt sensitive field values before writing them to +the database, and subsuquently decrypt them when retrieving data for the Admin +API, Developer Portal, or proxy business logic. Symmetric encryption keys are +managed based on the strategy defined below. + +**Default:** `off` + +--- + +#### keyring_strategy +{:.badge .enterprise} + +Defines the strategy implementation by which Kong nodes will manage symmetric +encryption keys. Please see the Kong Enterprise documentation for a detailed +description of each strategies. Acceptable values for this option are 'cluster' +and 'vault'. + +**Default:** `cluster` + +--- + +#### keyring_public_key +{:.badge .enterprise} + +Defines the filesystem path at which the public key of an RSA keypair resides. +This keypair is used for symmetric keyring import/ export, e.g., for disaster +recovery and optional bootstrapping. + +**Default:** none + +--- + +#### keyring_private_key +{:.badge .enterprise} + +Defines the filesystem path at which the private key of an RSA keypair resides. +This keypair is used for symmetric keyring import/ export, e.g., for disaster +recovery and optional bootstrapping. + +**Default:** none + +--- + +#### keyring_blob_path +{:.badge .enterprise} + +Defines the filesystem path at which Kong will backup the initial keyring +material. + +This option is useful largely for development purposes. + +**Default:** none + +--- + +#### keyring_vault_host +{:.badge .enterprise} + +Defines the Vault host at which Kong will fetch the encryption material. This +value should be defined in the format: + +`://:` + +**Default:** none + +--- + +#### keyring_vault_mount +{:.badge .enterprise} + +Defines the name of the Vault v2 KV secrets engine at which symmetric keys are +found. + +**Default:** none + +--- + +#### keyring_vault_path +{:.badge .enterprise} + +Defines the names of the Vault v2 KV path at which symmetric keys are found. + +**Default:** none + +--- + +#### keyring_vault_token +{:.badge .enterprise} + +Defines the token value used to communicate with the v2 KV Vault HTTP(S) API. + +**Default:** none + +--- + +#### untrusted_lua +{:.badge .enterprise} + +Controls loading of Lua functions from admin-supplied sources such as the Admin +API. LuaJIT bytecode loading is always disabled. + +**Warning:** LuaJIT is not designed as a secure runtime for running malicious +code, therefore you should properly protect your Admin API endpoint even with +sandboxing enabled. The sandbox only provides protection against trivial +attackers or unintentional modification of the Kong global environment. + +Accepted values are: `off`, `sandbox`, or `on`: + +* `off`: Disallow loading of any arbitrary Lua functions. The `off` option +disables any functionality that runs arbitrary Lua code, including the +Serverless Functions plugins and any transformation plugin that allows custom +Lua functions. + +* `sandbox`: Allow loading of Lua functions, but use a sandbox when executing +them. The sandboxed function has restricted access to the global environment and +only has access to standard Lua functions that will generally not cause harm to +the Kong Gateway node. + +* `on`: Functions have unrestricted access to the global environment and can +load any Lua modules. This is similar to the behavior in Kong Gateway prior to +2.3.0. + +The default `sandbox` environment does not allow importing other modules or +libraries, or executing anything at the OS level (for example, file read/write). +The global environment is also not accessible. + +Examples of `untrusted_lua = sandbox` behavior: + +* You can't access or change global values such as +`kong.configuration.pg_password` * You can run harmless lua: `local foo = 1 + +1`. However, OS level functions are not allowed, like: `os.execute('rm -rf +/*')`. + +For a full allowed/disallowed list, see: +https://github.com/kikito/sandbox.lua/blob/master/sandbox.lua + +To customize the sandbox environment, use the `untrusted_lua_sandbox_requires` +and `untrusted_lua_sandbox_environment` parameters below. + +**Default:** `sandbox` + +--- + +#### untrusted_lua_sandbox_requires +{:.badge .enterprise} + +Comma-separated list of modules allowed to be loaded with `require` inside the +sandboxed environment. Ignored if `untrusted_lua` is not `sandbox`. + +For example, say you have configured the Serverless pre-function plugin and it +contains the following `requires`: + +``` +local template = require "resty.template" +local split = require "kong.tools.utils".split +``` + +To run the plugin, add the modules to the allowed list: + +``` +untrusted_lua_sandbox_requires = resty.template, kong.tools.utils +``` + +**Warning:** Allowing certain modules may create opportunities to escape the +sandbox. For example, allowing `os` or `luaposix` may be unsafe. + +**Default:** none + +--- + +#### untrusted_lua_sandbox_environment +{:.badge .enterprise} + +Comma-separated list of global Lua variables that should be made available +inside the sandboxed environment. Ignored if `untrusted_lua` is not `sandbox`. + +**Warning**: Certain variables, when made available, may create opportunities +to escape the sandbox. + +**Default:** none + +--- + + + +[Penlight]: http://stevedonovan.github.io/Penlight/api/index.html +[pl.template]: http://stevedonovan.github.io/Penlight/api/libraries/pl.template.html +[templates]: https://github.com/kong/kong/tree/master/kong/templates diff --git a/app/gateway/2.6.x/reference/db-less-and-declarative-config.md b/app/gateway/2.6.x/reference/db-less-and-declarative-config.md new file mode 100644 index 000000000000..501c9664507a --- /dev/null +++ b/app/gateway/2.6.x/reference/db-less-and-declarative-config.md @@ -0,0 +1,287 @@ +--- +title: DB-less and Declarative Configuration +--- + +Traditionally, {{site.base_gateway}} has always required a database, which could be either PostgreSQL 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 PostgreSQL and Cassandra and its various settings. + +{{site.base_gateway}} can be run without a database using only in-memory storage for entities. We call this DB-less mode. When running {{site.base_gateway}} 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 + +## Declarative configuration + +The key idea in declarative configuration is 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 do that". "Declarative" 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 attained 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. + +## Set up Kong in DB-less mode + +To use {{site.base_gateway}} 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`. + +Command: + +``` +http :8001/ +``` + +Sample response: + +``` +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/2.1.0 +{ + "configuration:" { + ... + "database": "off", + ... + }, + ... + "version": "2.1.0" +} +``` + +{{site.base_gateway}} 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. + +Command: + +``` +http :8001/routes +``` + +Sample response: + +``` +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/2.1.0 + +{ + "data": [], + "next": null +} +``` + +## Creating a declarative configuration file + +{:.note} +> **Note:** We recommend using decK to manage your declarative configuration. +See the [decK documentation](/deck/) for more information. + +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. + +## Declarative configuration format + +The {{site.base_gateway}} declarative configuration format consists of lists of +entities and their attributes. This is a small yet complete +example that illustrates a number of features: + +```yaml +_format_version: "2.1" +_transform: true + +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: "2.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. + +The `_transform` metadata is an optional boolean (defaults to `true`), which +controls whether schema transformations will occur while importing. The rule +of thumb for using this field is: if you are importing plain-text credentials +(i.e. passwords), you likely want to set it to `true`, so that Kong will +encrypt/hash them before storing them in the database. If you are importing +**already hashed/encrypted** credentials, set `_transform` to `false` so that +the encryption does not happen twice. + +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 that 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 +``` + +## Check the 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 +``` + +## Load the file + +There are two ways to load a declarative configuration file into Kong: using +`kong.conf` or the Admin API. + +To load a declarative configuration file 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 +``` + +You can also load a declarative configuration file into a running +Kong node with the Admin API, using the `/config` endpoint. The +following example loads `kong.yml` using HTTPie: + +``` +http :8001/config config=@kong.yml +``` + +{:.important} +The `/config` endpoint replaces the entire set of entities in memory +with the ones specified in the given file. + +Or another way you can start Kong in DB-less mode is with a +declarative configuration in a string using the `KONG_DECLARATIVE_CONFIG_STRING` +environment variable. + +``` +export KONG_DATABASE=off +export KONG_DECLARATIVE_CONFIG_STRING='{"_format_version":"1.1", "services":[{"host":"httpbin.konghq.com","port":443,"protocol":"https", "routes":[{"paths":["/"]}]}],"plugins":[{"name":"rate-limiting", "config":{"policy":"local","limit_by":"ip","minute":3}}]}' +kong start +``` + +## 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 or dynamic creation of +entities. + +For current plugin compatibility, see [Plugin compatibility](/hub/plugins/compatibility/). diff --git a/app/gateway/2.6.x/reference/external-plugins.md b/app/gateway/2.6.x/reference/external-plugins.md new file mode 100644 index 000000000000..8c2a19058c3b --- /dev/null +++ b/app/gateway/2.6.x/reference/external-plugins.md @@ -0,0 +1,633 @@ +--- +title: Plugins in Other Languages + +--- + +## Introduction + +External plugins are those that run on a process separate from {{site.base_gateway}} itself, +enabling the use of any programming language for which an appropriate +plugin server is available. + +Each plugin server hosts one or more plugins and communicates with the +main {{site.base_gateway}} process through Unix sockets. If so configured, {{site.base_gateway}} can manage +those processes, starting, restarting and stopping as necessary. + +{{site.base_gateway}} currently maintains a Go language plugin server, +[go-pluginserver], the corresponding PDK library +package [go-pdk], the JavaScript language support [kong-js-pdk] +and Python language support [kong-python-pdk]. + +## {{site.base_gateway}} plugin server configuration + +The `pluginserver_names` property is a comma-separated list of names, one +for each plugin server process. These names are used to group each process' +properties and to annotate log entries. + +For each name, other properties can be defined: + +Property | Description | Default +---------|-------------|-------- +`pluginserver__socket` | Unix socket path | `/usr/local/kong/.socket` +`pluginserver__start_cmd` | Command to start the plugin server process | `/usr/local/bin/` +`pluginserver__query_cmd` | Command to dump available plugins' info | `/usr/local/bin/query_` + + +For example, you could set Go and Python plugins like this (assuming +an hypothetical Python plugin server called `pypluginserver.py`): + +``` +pluginserver_names = go,python + +pluginserver_go_socket = /usr/local/kong/go_pluginserver.sock +pluginserver_go_start_cmd = /usr/local/bin/go-pluginserver -kong-prefix /usr/local/kong/ -plugins-directory /usr/local/kong/go-plugins +pluginserver_go_query_cmd = /usr/local/bin/go-pluginserver -dump-all-plugins -plugins-directory /usr/local/kong/go-plugins + +pluginserver_python_socket = /usr/local/kong/python_pluginserver.sock +pluginserver_python_start_cmd = /usr/local/bin/kong-python-pluginserver +pluginserver_python_query_cmd = /usr/local/bin/kong-python-pluginserver --dump-all-plugins +``` + +To enable those plugins, add the each plugin name to the `plugins` config. Assume we have those hello plugins +in each language: + +``` +plugins = bundled, go-hello, js-hello, py-hello +``` + +{:.note} +> **Note:** The `pluginserver_XXX_start_cmd` and `pluginserver_XXX_query_cmd` commands use + a limited default `PATH` variable. In most cases, you have to specify the full executable + path instead. + +### Legacy configuration + +{{site.base_gateway}} versions 2.0.x to 2.2.x supported only Go external plugins and a single +plugin server using a different configuration style. Starting with {{site.base_gateway}} version 2.3, +the old style is recognized and internally transformed to the new style. + +If property `pluginserver_names` isn't defined, the legacy properties +`go_plugins_dir` and `go_pluginserver_exe` are tried: + +Property | Description | Default +---------|-------------|-------- +`go_plugins_dir` | Directory with Go plugins | `off`, meaning to disable Go plugins +`go_pluginserver_exe` | Path to the go-pluginserver executable | `/usr/local/bin/go-pluginserver` + +Notes: + +- The old style doesn't allow multiple plugin servers. +- Version 0.5.0 of [go-pluginserver] requires the old style configuration. +- The new style configuration requires v0.6.0 of [go-pluginserver] + +## Developing Go plugins + +{{site.base_gateway}} support for the Go language consist of two parts: + +- [go-pdk] as a library, provides Go functions to access {{site.base_gateway}} features of the [PDK][kong-pdk]. +- [go-pluginserver] an executable to dynamically load plugins written in Go. + + +Notes: + +The {{site.base_gateway}} version 2.3 allows multiple plugin servers; in particular +it's now possible to write single-plugin servers, in effect plugins as +microservices. To help with this, version v0.6.0 of the [go-pdk] package +includes an optional plugin server. See [Embedded Server](#embedded-server) +for more information. + +The [go-pluginserver] process is still supported. Its main advantage is +that it's a single process for any number of plugins, but the dynamic +loading of plugins has proven challenging under the Go language (unlike +the microservice architecture, which is well supported by the language +and tools). + +### Development + +To write a {{site.base_gateway}} plugin in Go, you need to: + +1. Define a structure type to hold configuration. +2. Write a `New()` function to create instances of your structure. +3. Add methods on that structure to handle phases. + + If you want a dynamically-loaded plugin to be used with [go-pluginserver]: + +4. Compile your Go plugin with `go build -buildmode plugin`. +5. Put the resulting library (the `.so` file) into the `go_plugins_dir` directory. + + If you want a standalone plugin microservice: + +4. Include the `go-pdk/server` sub-library. +5. Add a `main()` function that calls `server.StartServer(New, Version, Priority)`. +6. Compile as an executable with `go build`. + +**Note**: Check out [this repository](https://github.com/Kong/go-plugins) +for example Go plugins. + +#### 1. Configuration Structure + +Plugins written in Lua define a schema to specify how to read and validate +configuration data coming from the datastore or the Admin API. Since Go is a +statically-typed language, all that specification is handled by defining a +configuration structure: + +```go +type MyConfig struct { + Path string + Reopen bool +} +``` + +Public fields (that is, those starting with a capital letter) will be filled +with configuration data. If you want them to have a different name in the +datastore, add field tags as defined in the `encoding/json` package: + +```go +type MyConfig struct { + Path string `json:my_file_path` + Reopen bool `json:reopen` +} +``` + +#### 2. New() Constructor + +Your plugin must define a function called `New` that creates an instance of this type +and returns as an `interface{}`. In most cases, it’s just this: + +```go +func New() interface{} { + return &MyConfig{} +} +``` + +You can add more fields to the structure and they’ll be passed around, but +there are no guarantees about the lifetime or quantity of configuration +instances. + +#### 3. Phase Handlers + +Similarly to {{site.base_gateway}} Lua plugins, you can implement custom logic to be executed at +various points of the request processing lifecycle. For example, to execute +custom Go code in the access phase, define a function named `Access`: +```go +func (conf *MyConfig) Access (kong *pdk.PDK) { + ... +} +``` + +The phases you can implement custom logic for are as follows, and the expected function +signature is the same for all of them: + +- `Certificate` +- `Rewrite` +- `Access` +- `Response` +- `Preread` +- `Log` + +Similar to Lua plugins, the presence of the `Response` handler automatically enables the buffered proxy mode. + +#### 4. Version and Priority + +Similarly to {{site.base_gateway}} Lua plugins, you can define the version number and priority of execution +by having following lines in plugin code: + +```go +const Version = "1.0.0" +const Priority = 1 +``` + +{{site.base_gateway}} executes plugins from highest priority to lowest ones. + +### Embedded server + +Each plugin can be a microservice, compiled as a standalone executable. + +To use the embedded server, include `github.com/Kong/go-pdk/server` in +the imports list, and add a `main()` function: + +```go +func main () { + server.StartServer(New, Version, Priority) +} +``` + +Note that the `main()` function must have a `package main` line at the +top of the file. + +Then, a standard Go build creates an executable. There are no extra go-pluginserver, +no plugin loading, and no compiler/library/environment compatibility issues. + +The resulting executable can be placed somewhere in your path (for example, +`/usr/local/bin`). The common `-h` flag shows a usage help message: + +``` +$ my-plugin -h + +Usage of my-plugin: + -dump + Dump info about plugins + -help + Show usage info + -kong-prefix string + Kong prefix path (specified by the -p argument commonly used in the Kong CLI) (default "/usr/local/kong") +``` + +When run without arguments, it creates a socket file with the +`kong-prefix` and the executable name, appending `.socket`. For example, +if the executable is `my-plugin`, it would be +`/usr/local/kong/my-plugin.socket` by default. + +#### Example configuration + +Two standalone plugins, called `my-plugin` and `other-one`: + +``` +pluginserver_names = my-plugin,other-one + +pluginserver_my_plugin_socket = /usr/local/kong/my-plugin.socket +pluginserver_my_plugin_start_cmd = /usr/local/bin/my-plugin +pluginserver_my_plugin_query_cmd = /usr/local/bin/my-plugin -dump + +pluginserver_other_one_socket = /usr/local/kong/other-one.socket +pluginserver_other_one_start_cmd = /usr/local/bin/other-one +pluginserver_other_one_query_cmd = /usr/local/bin/other-one -dump + +``` + +Note that the socket and start command settings coincide with +their defaults, so they can be omitted: + +``` +pluginserver_names = my-plugin,other-one +pluginserver_my_plugin_query_cmd = /usr/local/bin/my-plugin -dump +pluginserver_other_one_query_cmd = /usr/local/bin/other-one -dump +``` + +## Developing JavaScript plugins + +{{site.base_gateway}} support for the JavaScript language is provided by [kong-js-pdk]. +The library provides a plugin server to provide runtime for JavaScript plugins, and +functions to access {{site.base_gateway}} features of the [PDK][kong-pdk]. + +TypeScript is also supported in the following ways: + +- [kong-js-pdk] includes type definitions for PDK functions that allow type checking +when developing plugins in TypeScript. +- Plugin written in TypeScript can be loaded directly and transpiled on the fly. + +### Example configuration + +[kong-js-pdk] can be installed using `npm`. To install the plugin server binary globally: + +``` +npm install kong-pdk -g +``` + +Assume the plugins are stored in `/usr/local/kong/js-plugins`: + +``` +pluginserver_names = js +pluginserver_js_socket = /usr/local/kong/js_pluginserver.sock +pluginserver_js_start_cmd = /usr/local/bin/kong-js-pluginserver --plugins-directory /usr/local/kong/js-plugins +pluginserver_js_query_cmd = /usr/local/bin/kong-js-pluginserver --plugins-directory /usr/local/kong/js-plugins --dump-all-plugins +``` + +### Development + +Install [kong-js-pdk] in your local development directory: + +``` +npm install kong-pdk --save +``` + +A valid JavaScript plugin implementation should export the following object: + +```javascript +module.exports = { + Plugin: KongPlugin, + Schema: [ + { message: { type: "string" } }, + ], + Version: '0.1.0', + Priority: 0, +} +``` + +`Plugin` attribute defines the class that implements this plugin. `Schema` defines the config +schema of plugin, it shares the same syntax as it's a Lua plugin. `Version` and `Priority` +defines the version number and priority of execution respectively. + +**Note**: Check out [this repository](https://github.com/Kong/kong-js-pdk/tree/master/examples) +for example JavaScript and TypeScript plugins. + +#### 1. Phase Handlers + +Similarly to {{site.base_gateway}} Lua plugins, you can implement custom logic to be executed at +various points of the request processing lifecycle. For example, to execute +custom JavaScript code in the access phase, define a function named `access`: + +```javascript +class KongPlugin { + constructor(config) { + this.config = config + } + async access(kong) { + // ... + } +} +``` + +The phases you can implement custom logic for are as follows, and the expected function +signature is the same for all of them: + +- `certificate` +- `rewrite` +- `access` +- `response` +- `preread` +- `log` + +Similar to Lua plugins, the presence of the `response` handler automatically enables the buffered proxy mode. + +#### 2. PDK functions + +[kong-js-pdk] invokes PDK functions in Kong through network-based IPC (inter-process communication). +So each function returns a Promise +instance; it's convenient to use `async`/`await` keywords in phase handlers for better readability. + +```javascript +class KongPlugin { + constructor(config) { + this.config = config + } + async access(kong) { + let host = await kong.request.getHeader("host") + // do something to host + } +} +``` + +Or consume Promise in a traditional way: + +```javascript +class KongPlugin { + constructor(config) { + this.config = config + } + async access(kong) { + kong.request.getHeader("host") + .then((host) => { + // do something to host + }) + } +} +``` + +#### 3. Plugin dependencies + +When using the plugin server, plugins are allowed to have extra dependencies, as long as the +directory that holds plugin source code also includes a `node_modules` directory. + +Assuming plugins are stored under `/usr/local/kong/js-plugins`, the extra dependencies are +then defined in `/usr/local/kong/js-plugins/package.json`. Developers also need to +run `npm install` under `/usr/local/kong/js-plugins` to install those dependencies locally +into `/usr/local/kong/js-plugins/node_modules`. + +Note in this case, the node version and architecture that runs the plugin server and +the one that runs `npm install` under plugins directory must match. For example, it may break +when you run `npm install` under macOS and mount the working directory into a Linux container. + +### Testing + +[kong-js-pdk] provides a mock framework to test plugin code correctness through `jest`. + +Install `jest` as a development dependency, and add the `test` script in `package.json`: + +``` +npm install jest --save-dev +``` + +The `package.json` has content similar to the following: + + { + "scripts": { + "test": "jest" + }, + "devDependencies": { + "jest": "^26.6.3", + "kong-pdk": "^0.3.2" + } + } + +Run the test through npm with: + +``` +npm test +``` + +**Note**: Check out [this repository](https://github.com/Kong/kong-js-pdk/tree/master/examples) +for examples on how to write test using `jest`. + +## Developing Python plugins + +{{site.base_gateway}} support for the Python language is provided by [kong-python-pdk]. +The library provides a plugin server to provide runtime for Python plugins, and +functions to access {{site.base_gateway}} features of the [PDK][kong-pdk]. + +### Example configuration + +[kong-python-pdk] can be installed using `pip`. To install the plugin server binary and PDK globally, use: + +``` +pip3 install kong-pdk +``` + +Assume the plugins are stored in `/usr/local/kong/python-plugins`: + +``` +pluginserver_names = python +pluginserver_python_socket = /usr/local/kong/python_pluginserver.sock +pluginserver_python_start_cmd = /usr/local/bin/kong-python-pluginserver --plugins-directory /usr/local/kong/python-plugins +pluginserver_python_query_cmd = /usr/local/bin/kong-python-pluginserver --plugins-directory /usr/local/kong/python-plugins --dump-all-plugins +``` + +### Development + +A valid Python plugin implementation has following attributes: + +```python +Schema = ( + { "message": { "type": "string" } }, +) +version = '0.1.0' +priority = 0 +class Plugin(object): + pass +``` + +A class named `Plugin` defines the class that implements this plugin. `Schema` defines the config +schema of plugin, it shares the same syntax as it's a Lua plugin. `version` and `priority` +defines the version number and priority of execution respectively. + +**Note**: Check out [this repository](https://github.com/Kong/kong-python-pdk/tree/master/examples) +for example Python plugins and [API reference](https://kong.github.io/kong-python-pdk/py-modindex.html). + +#### 1. Phase Handlers + +Similarly to {{site.base_gateway}} Lua plugins, you can implement custom logic to be executed at +various points of the request processing lifecycle. For example, to execute +custom Go code in the access phase, define a function named `access`: + +```python +class Plugin(object): + def __init__(self, config): + self.config = config + def access(self, kong): + pass +``` + +The phases you can implement custom logic for are as follows, and the expected function +signature is the same for all of them: + +- `certificate` +- `rewrite` +- `access` +- `response` +- `preread` +- `log` + +Similar to Lua plugins, the presence of the `response` handler automatically enables the buffered proxy mode. + +#### 2. Type hints + +[kong-python-pdk] supports [type hint](https://www.python.org/dev/peps/pep-0484/) in Python 3.x. To use type lint +and autocomplete in IDE, user can annotate the `kong` parameter in phase handler: + +```python +import kong_pdk.pdk.kong as kong +class Plugin(object): + def __init__(self, config): + self.config = config + def access(self, kong: kong.kong): + host, err = kong.request.get_header("host") +``` + +### Embedded server + +Each plugin can be a microservice. To use the embedded server, use the following code: + +```python +if __name__ == "__main__": + from kong_pdk.cli import start_dedicated_server + start_dedicated_server("py-hello", Plugin, version, priority) +``` + +Note the first argument to `start_dedicated_server` defines the plugin name and must +be unique across all languages. + +#### Example configuration + +Two standalone plugins, called `my-plugin` and `other-one`: + +``` +pluginserver_names = my-plugin,other-one +pluginserver_my_plugin_socket = /usr/local/kong/my-plugin.socket +pluginserver_my_plugin_start_cmd = /path/to/my-plugin.py +pluginserver_my_plugin_query_cmd = /path/to/my-plugin.py --dump +pluginserver_other_one_socket = /usr/local/kong/other-one.socket +pluginserver_other_one_start_cmd = /path/to/other-one.py +pluginserver_other_one_query_cmd = /path/to/other-one.py -dump +``` + +Note that the socket and start command settings coincide with +their defaults, so they can be omitted: + +``` +pluginserver_names = my-plugin,other-one +pluginserver_my_plugin_query_cmd = /path/to/my-plugin --dump +pluginserver_other_one_query_cmd = /path/to/other-one --dump +``` + +### Concurrency model + +Python plugin server and embedded server supports multiple concurrency model. By default, +the server starts in multi-threading mode. + +If your workload is IO intensive, consider the gevent model by adding `-g` to pluginserver's +start_cmd. +If your workload is CPU intensive, consider the multi-processing model by adding `-m` to pluginserver's +start_cmd. + + +## Performance for external plugins + +Depending on implementation details, Go plugins are able to use multiple CPU cores +and so perform best on a multi-core system. JavaScript plugins are currently +single-core only and there's no dedicated plugin server support. +Python plugins can use a dedicated plugin server to span workload to +multiple CPU cores as well. + +Unlike Lua plugins where invoking PDK functions are handled in local processes, +calling PDK functions in external plugins implies inter-process communications and so is a +relatively expensive operation. Because of the expense of calling PDK functions in external plugins, the performance of Kong using external plugins is +highly related to the number of IPC (inter-process communication) calls in each request. + +The following graph demonstrates the correlation between performance and count of IPC +calls per request. Numbers of RPS and latency are removed as they are dependent on +hardware and to avoid confusion. + +
    + +
    + +## Use external plugins in container and Kubernetes + +To use plugins requiring external plugin servers, both the plugin servers and the plugins themselves need to be installed inside the {{ site.base_gateway }} container. + +For plugins written in Golang, build external plugins in embedded server mode in a builder container +and copy or mount the binary artifacts into the {{ site.base_gateway }} container. +For plugins written in JavaScript, first install Node and `npm`, then use `npm` to install `kong-pdk`, and finally +copy or mount the plugins source code into the {{ site.base_gateway }} container. +For plugins written in Python, install Python and `pip`. Then use `pip` to install `kong-pdk`. Finally, +copy or mount the plugin's source code into the {{ site.base_gateway }} container. + +Refer to previous sections on how to configure {{ site.base_gateway }} after you build the image +or create the container. + +{:.note} +> **Note:** Official {{ site.base_gateway }} images are configured to run as the `nobody` user. When building a custom image, to copy files into +the {{ site.base_gateway }} image, you must temporarily set the user to `root`. + +```dockerfile +FROM kong +USER root +# Example for GO: +COPY your-go-plugin /usr/local/bin/your-go-plugin +# Example for JavaScript: +RUN apk update && apk add nodejs npm && npm install -g kong-pdk +COPY you-js-plugin /path/to/your/js-plugins/you-js-plugin +# Example for Python +# PYTHONWARNINGS=ignore is needed to build gevent on Python 3.9 +RUN apk update && \ + apk add python3 py3-pip python3-dev musl-dev libffi-dev gcc g++ file make && \ + PYTHONWARNINGS=ignore pip3 install kong-pdk +COPY you-py-plugin /path/to/your/py-plugins/you-py-plugin +# reset back the defaults +USER kong +ENTRYPOINT ["/docker-entrypoint.sh"] +EXPOSE 8000 8443 8001 8444 +STOPSIGNAL SIGQUIT +HEALTHCHECK --interval=10s --timeout=10s --retries=10 CMD kong health +CMD ["kong", "docker-start"] +``` +--- + +[go-pluginserver]: https://github.com/Kong/go-pluginserver +[go-pluginserver-makefile]: https://github.com/Kong/go-pluginserver/blob/master/Makefile +[go-plugins]: https://github.com/Kong/go-plugins +[go-pdk]: https://github.com/Kong/go-pdk +[kong-pdk]: /gateway/latest/plugin-development/ +[go-hello]: https://github.com/Kong/go-plugins/blob/master/go-hello.go +[kong-js-pdk]: https://github.com/Kong/kong-js-pdk +[kong-python-pdk]: https://github.com/Kong/kong-python-pdk diff --git a/app/gateway/2.6.x/reference/health-checks-circuit-breakers.md b/app/gateway/2.6.x/reference/health-checks-circuit-breakers.md new file mode 100644 index 000000000000..162d0626dd20 --- /dev/null +++ b/app/gateway/2.6.x/reference/health-checks-circuit-breakers.md @@ -0,0 +1,351 @@ +--- +title: Health Checks and Circuit Breakers Reference +--- + +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, +marking them as healthy or unhealthy based on 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 to requests. + +## Defining 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 + } + }, + "threshold": 0 + }, + "slots": 10 +} +``` + +If an upstream is unhealthy (the available capacity % is less than the configured +threshold), 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 load balancer, 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.* + +### Upstreams + +Along with health check functionality on individual targets, Upstreams also +have a notion of health. The health of an Upstream is determined based on the +status of its Targets. + +Configuration of the Upstream's health is done though the property +`healthchecks.threshold`. This is a percentage of minimum available target +"weight" (capacity) for the Upstream to be considered healthy. + +Here is a simple example: + +- Assume an Upstream configured with `healthchecks.threshold=55`. +- It has 5 targets, each with `weight=100`, so the total weight in the ring-balancer is 500. + +When failures start to occur, the circuit-breaker for the first target trips. +It is now considered unhealthy. This means that in the ring-balancer, 20% of +the capacity is now unhealthy (100 weight out of 500). This is still above the +threshold of 55, so the remaining targets will serve the traffic of the failed +one. + +When a second failure occurs, another target fails, and another 100 weight is lost +as unhealthy. Now the ring-balancer operates at 60% of its capacity, but still +within the configured threshold. + +If we assume that the two failures occurred due to a system overload, we can now assume +that the remaining 60% will also not be able to cope with the full load and soon a third +node will fail, reducing healthy capacity to 40%. At this point, the Upstream health +will be less than its threshold, and it will be marked as unhealthy itself. + +Once it enters an unhealthy state, the Upstream will only return errors. This lets the +targets/services recover from the cascading failure they were experiencing. + +Once the Targets start recovering and the Upstream's available capacity passes the +threshold again, the health status of the ring-balancer will automatically be updated. + +## 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} +> **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`. + +### 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. + +## 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][upstreamobject] 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. + +[ringbalancer]: /gateway/{{page.release}}/reference/loadbalancing#ring-balancer +[ringtarget]: /gateway/{{page.release}}/reference/loadbalancing#target +[upstream]: /gateway/{{page.release}}/reference/loadbalancing#upstream +[targetobject]: /gateway/{{page.release}}/admin-api#target-object +[addupstream]: /gateway/{{page.release}}/admin-api#add-upstream +[clustering]: /gateway/{{page.release}}/reference/clustering +[upstreamobject]: /gateway/{{page.release}}/admin-api#upstream-object +[balancercaveats]: /gateway/{{page.release}}/reference/loadbalancing#balancing-caveats +[dnscaveats]: /gateway/{{page.release}}/reference/loadbalancing#dns-caveats diff --git a/app/gateway/2.6.x/reference/loadbalancing.md b/app/gateway/2.6.x/reference/loadbalancing.md new file mode 100644 index 000000000000..be36d9cfd71b --- /dev/null +++ b/app/gateway/2.6.x/reference/loadbalancing.md @@ -0,0 +1,348 @@ +--- +title: Load Balancing Reference +--- + +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 load balancing + +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 hosts file. + +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. + +### 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. + +### 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`. + +### 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]. + +### 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. + +- DNS is carried over UDP with a default limit of 512 Bytes. If there are many entries +to be returned, a DNS Server will respond with partial data and set a truncate flag, +indicating there are more entries unsent. +DNS clients, including Kong's, will then make a second request over TCP to retrieve the full +list of entries. + +- Some nameservers by default do not respond with the truncate flag, but trim the response +to be under 512 byte UDP size. + - Consul is an example. Consul, in its default configuration, returns up to the first +three entries only, and does not set the truncate flag to indicate there are remaining entries unsent. +Consul includes an option to enable the truncate flag. Please refer to [Consul documentation](https://www.consul.io/docs/agent/options.html#enable_truncate) +for more information. + +- If a deployed nameserver does not provide the truncate flag, the pool +of upstream instances might be loaded inconsistently. 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 keep all upstream services in use. + +- 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. + +## 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, for example, "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`. + +### 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' +(which can be overwritten before proxying, using `upstream`'s property +`host_header`) will be load balanced over the targets. A ring-balancer has a +maximum predefined 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. + +Within the balancer there are the positions (from 1 up to the value defined in the `slots` attribute), +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`, while +also having cheap operations when inserting/deleting targets. + +Detailed information on adding and manipulating +upstreams is available in the `upstream` section of the +[Admin API reference][upstream-object-reference]. + +### Target + +A target is an ip address/hostname with a port that identifies an instance of +a backend service. Each upstream can have many targets. +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. + +### Balancing algorithms + +The ring-balancer supports the following load balancing algorithms: `round-robin`, +`consistent-hashing`, and `least-connections`. By default, a ring-balancer +uses the `round-robin` algorithm, which provides a well-distributed weighted +round-robin over the targets. + +When using the `consistent-hashing` algorithm, the input for the hash can be either +`none`, `consumer`, `ip`, `header`, or `cookie`. When set to `none`, the +`round-robin` scheme will be used, and hashing will be disabled. The `consistent-hashing` +algorithm supports a primary and a fallback hashing attribute; in case the primary +fails (e.g., if the primary is set to `consumer`, but no Consumer is authenticated), +the fallback attribute is used. + +Supported hashing attributes are: + +- `none`: Do not use `consistent-hashing`; use `round-robin` instead (default). +- `consumer`: Use the Consumer ID as the hash input. If no Consumer ID is available, + it will fall back on the Credential ID (for example, in case of an external authentication mechanism like LDAP). +- `ip`: Use the originating IP address as the hash input. Review the configuration + settings for [determining the real IP][real-ip-config] when using this. +- `header`: Use a specified header as the hash input. The header name is + specified in either `hash_on_header` or `hash_fallback_header`, depending on whether + `header` is a primary or fallback attribute, respectively. +- `cookie`: Use a specified cookie with a specified path as the hash input. + The cookie name is specified in the `hash_on_cookie` field and the path is + specified in the `hash_on_cookie_path` field. If the specified 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 `consistent-hashing` algorithm is based on _Consistent Hashing_ (or the +_Ketama Principle_), which ensures that when the balancer gets modified by +a change in its targets (adding, removing, failing, or changing weights), only +the minimum number of hashing losses occur. This maximizes upstream cache hits. + +The ring-balancer also supports the `least-connections` algorithm, which selects +the target with the lowest number of connections, weighted by the Target's +`weight` attribute. + +For more information on the exact settings see the `upstream` section of the +[Admin API reference][upstream-object-reference]. + +### 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 (for example, 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`. + +# 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://localhost:8001/upstreams \ + --data "name=address.v1.service" + +# add two targets to the upstream +$ curl -X POST http://localhost:8001/upstreams/address.v1.service/targets \ + --data "target=192.168.34.15:80" + --data "weight=100" +$ curl -X POST http://localhost: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://localhost: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://localhost: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://localhost:8001/upstreams \ + --data "name=address.v2.service" + +# add targets to the upstream +$ curl -X POST http://localhost:8001/upstreams/address.v2.service/targets \ + --data "target=192.168.34.17:80" + --data "weight=100" +$ curl -X POST http://localhost: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://localhost: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. + +# 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://localhost:8001/upstreams/address.v2.service/targets \ + --data "target=192.168.34.17:80" + --data "weight=1000" + +# second target at 0 +$ curl -X POST http://localhost: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://localhost:8001/upstreams/address.v2.service/targets \ + --data "target=192.168.34.17:80" + --data "weight=900" + +# second target at 100 +$ curl -X POST http://localhost: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. + +[upstream-object-reference]: /gateway/{{page.release}}/admin-api#upstream-object +[target-object-reference]: /gateway/{{page.release}}/admin-api#target-object +[dns-order-config]: /gateway/{{page.release}}/reference/configuration/#dns_order +[real-ip-config]: /gateway/{{page.release}}/reference/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/gateway/2.6.x/reference/proxy.md b/app/gateway/2.6.x/reference/proxy.md new file mode 100644 index 000000000000..7bf80c628bb0 --- /dev/null +++ b/app/gateway/2.6.x/reference/proxy.md @@ -0,0 +1,1368 @@ +--- +title: Proxy Reference +--- + +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 the following configuration +properties: + +- `proxy_listen`, which defines a list of addresses/ports on which Kong will + accept **public HTTP (gRPC, WebSocket, etc) 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). +{% include_cached /md/admin-listen.md release=page.release desc='short' %} +- `stream_listen`, which is similar to `proxy_listen` but for Layer 4 (TCP, TLS) + generic proxy. This is turned off by default. + +## 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/connections 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. + +## Overview + +From a high-level perspective, Kong listens for HTTP traffic on its configured +proxy port(s) (`8000` and `8443` by default) and L4 traffic on explicitly configured +`stream_listen` ports. Kong will evaluate any incoming +HTTP request or L4 connection 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 may be 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. Routes have +special attributes that are used for routing - matching incoming HTTP requests. +Routing attributes differ by subsystem (HTTP/HTTPS, gRPC/gRPCS, and TCP/TLS). + +Subsystems and routing attributes: +- `http`: `methods`, `hosts`, `headers`, `paths` (and `snis`, if `https`) +- `tcp`: `sources`, `destinations` (and `snis`, if `tls`) +- `grpc`: `hosts`, `headers`, `paths` (and `snis`, if `grpcs`) + +If one attempts to configure a Route with a routing attribute it doesn't support +(e.g., an `http` route with `sources` or `destinations` fields), an error message +will be reported: + +``` +HTTP/1.1 400 Bad Request +Content-Type: application/json +Server: kong/ + +{ + "code": 2, + "fields": { + "sources": "cannot set 'sources' when 'protocols' is 'http' or 'https'" + }, + "message": "schema violation (sources: cannot set 'sources' when 'protocols' is 'http' or 'https')", + "name": "schema violation" +} +``` + +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" +} +``` + +## 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 entry point 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. + +## Routes and matching capabilities + +Let's now discuss how Kong matches a request against the configured routing +attributes. + +Kong supports native proxying of HTTP/HTTPS, TCP/TLS, and GRPC/GRPCS protocols; +as mentioned earlier, each of these protocols accept a different set of routing +attributes: +- `http`: `methods`, `hosts`, `headers`, `paths` (and `snis`, if `https`) +- `tcp`: `sources`, `destinations` (and `snis`, if `tls`) +- `grpc`: `hosts`, `headers`, `paths` (and `snis`, if `grpcs`) + +Note that all of these fields are **optional**, but at least **one of them** +must be specified. + +For a request to match a Route: + +- The request **must** include **all** of the configured fields +- The values of the fields in the request **must** match at least one of the + configured values (While the field configurations 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 routing properties work together, let's explore +each property individually. + +### Request header + +Kong supports routing by arbitrary HTTP headers. A special case of this +feature is routing by the Host header. + +Routing a request based on its Host header is the most straightforward way to +proxy traffic through 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, and is represented 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 +``` + +Similarly, any other header can be used for routing: + +``` +$ curl -i -X POST http://localhost:8001/routes/ \ + -d 'headers.region=north' +HTTP/1.1 201 Created +``` + +Incoming requests containing a `Region` header set to `North` will be routed to +said Route. + +``` +Region: North +``` + +#### 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 +``` + +#### 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 +``` + +### Additional request headers + +It's possible to route requests by other headers besides `Host`. + +To do this, use the `headers` property in your Route: + +```json +{ + "headers": { "version": ["v1", "v2"] }, + "service": { + "id": "..." + } +} +``` + +Given a request with a header such as: + +```http +GET / HTTP/1.1 +version: v1 +``` + +This request will be routed through to the Service. The same will happen with this one: + +```http +GET / HTTP/1.1 +version: v2 +``` + +But this request will not be routed to the Service: + +```http +GET / HTTP/1.1 +version: v3 +``` + +**Note**: The `headers` keys are a logical `AND` and their values a logical `OR`. + +### Request path + +Another way for a Route to be matched is via request paths. To satisfy this +routing condition, a client request's normalized path **must** be prefixed with one of the +values of the `paths` attribute. + +For example, with a Route configured like so: + +```json +{ + "paths": ["/service", "/hello/world"] +} +``` + +The following requests would be matched: + +```http +GET /service HTTP/1.1 +Host: example.com +``` + +```http +GET /service/resource?param=value HTTP/1.1 +Host: example.com +``` + +```http +GET /hello/world/resource HTTP/1.1 +Host: anything.com +``` + +For each of these requests, Kong detects that their normalized 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. + +#### Using Regex 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 Regex to a Route at the same time. + +For a path to be considered as Regex, it must fall **outside** of the following regex: + +``` +^[a-zA-Z0-9\.\-_~/%]*$ +``` + +In other words, if a path contains any character that is **not** alphanumerical, dot (`.`), +dash (`-`), underscore (`_`), tilde (`~`), forward-slash (`/`), or percent (`%`), then +it will be considered a Regex path. This determination is done on a per-path basis +and it is allowed to mix plain text and regex paths inside the same `paths` array of the same +Route object. + +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 Regex 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). + +**Note**: Regex matching is in general very fast, but it is possible to +construct expressions that take a very long time to determine that they don't +actually match. This happens when the expression results in a "backtrace +exponential explosion", which means that there's an astronomical number of +tests to be performed before it's conclusive that they're all negative. +If undetected, this could take hours to finish with a single regular expression. +The [PCRE](http://pcre.org/) engine automatically detects most types of this +and replaces with more direct approaches, but there are more complex expressions +that could result in this scenario. + +To limit the worst-case scenario, Kong applies the OpenResty +[`lua_regex_match_limit`](https://github.com/openresty/lua-nginx-module#lua_regex_match_limit) +to ensure that any regex operation terminates in around two seconds in the +worst case. Apart from that, a smaller limit is applied to some "critical" +regex operations, like those for path selection, in order to terminate them +within two milliseconds, at most. + +##### Evaluation order + +As previously mentioned, Kong evaluates prefix paths by length, the longest +prefix paths are evaluated first. However, Kong will evaluate Regex paths based +on the `regex_priority` attribute of Routes from highest priority to lowest. +Regex paths are furthermore evaluated before prefix paths. + +Consider the following Routes: + +```json +[ + { + "paths": ["/status/\d+"], + "regex_priority": 0 + }, + { + "paths": ["/version/\d+/status/\d+"], + "regex_priority": 6 + }, + { + "paths": ["/version"], + }, + { + "paths": ["/version/any/"], + } +] +``` + +In this scenario, Kong will evaluate incoming requests against the following +defined URIs, in this order: + +1. `/version/\d+/status/\d+` +2. `/status/\d+` +3. `/version/any/` +4. `/version` + +Take care to avoid writing Regex rules that are overly broad and may consume +traffic intended for a prefix rule. Adding a rule with the path `/version/.*` to +the ruleset above would likely consume some traffic intended for the `/version` +prefix path. If you see unexpected behavior, sending `Kong-Debug: 1` in your +request headers will indicate the matched Route ID in the response headers for +troubleshooting purposes. + +As usual, a request must still match a Route's `hosts` and `methods` properties +as well, and Kong will traverse your Routes until it finds one that [matches +the most rules](#matching-priorities). + +##### 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 other routing attributes), 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" } +``` + +##### Escaping special characters + +Next, it is worth noting that characters found in Regex 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. + +#### 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: ... +``` + +#### Normalization behavior + +To prevent trivial Route match bypass, the incoming request URI from client +is always normalized according to [RFC 3986](https://tools.ietf.org/html/rfc3986) +before router matching occurs. Specifically, the following normalization techniques are +used for incoming request URIs, which are selected because they generally do not change +semantics of the request URI: + +1. Percent-encoded triplets are converted to uppercase. For example: `/foo%3a` becomes `/foo%3A`. +2. Percent-encoded triplets of unreserved characters are decoded. For example: `/fo%6F` becomes `/foo`. +3. Dot segments are removed as necessary. For example: `/foo/./bar/../baz` becomes `/foo/baz`. +4. Duplicate slashes are merged. For example: `/foo//bar` becomes `/foo/bar`. + +The `paths` attribute of the Route object are also normalized. It is achieved by first determining +if the path is a plain text or regex path. Based on the result, different normalization techniques +are used. + +For plain text Route path: + +Same normalization technique as above is used, that is, methods 1 through 4. + +For regex Route path: + +Only methods 1 and 2 are used. In addition, if the decoded character becomes a regex +meta character, it will be escaped with backslash. + +Kong normalizes any incoming request URI before performing router +matches. As a result, any request URI sent over to the upstream services will also +be in normalized form that preserves the original URI semantics. + +### 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). + +### Request source + +{:.note} +> **Note:** This section only applies to TCP and TLS routes. + +The `sources` routing attribute allows +matching a route by a list of incoming connection IP and/or port sources. + +The following Route allows routing via a list of source IP/ports: + +```json +{ + "protocols": ["tcp", "tls"], + "sources": [{"ip":"10.1.0.0/16", "port":1234}, {"ip":"10.2.2.2"}, {"port":9123}], + "id": "...", +} +``` + +TCP or TLS connections originating from IPs in CIDR range "10.1.0.0/16" or IP +address "10.2.2.2" or Port "9123" would match such Route. + +### Request destination + +{:.note} +> **Note:** This section only applies to TCP and TLS routes. + +The `destinations` attribute, similarly to `sources`, +allows matching a route by a list of incoming connection IP and/or port, but +uses the destination of the TCP/TLS connection as routing attribute. + +### Request SNI + +When using secure protocols (`https`, `grpcs`, or `tls`), a [Server +Name Indication][SNI] can be used as a routing attribute. The following Route +allows routing via SNIs: + +```json +{ + "snis": ["foo.test", "example.com"], + "id": "..." +} +``` + +Incoming requests with a matching hostname set in the TLS connection's SNI +extension would be routed to this Route. As mentioned, SNI routing applies not +only to TLS, but also to other protocols carried over TLS - such as HTTPS and +If multiple SNIs are specified in the Route, any of them can match with the incoming request's SNI. +with the incoming request (OR relationship between the names). + +The SNI is indicated at TLS handshake time and cannot be modified after the TLS connection has +been established. This means, for example, that multiple requests reusing the same keepalive connection +will have the same SNI hostname while performing router match, regardless of the `Host` header. +has been established. This means keepalive connections that send multiple requests +will have the same SNI hostnames while performing router match +(regardless of the `Host` header). + +Please note that creating a route with mismatched SNI and `Host` header matcher +is possible, but generally discouraged. + +## Matching priorities + +A Route may define matching rules based on its `headers`, `hosts`, `paths`, and +`methods` (plus `snis` for secure routes - `"https"`, `"grpcs"`, `"tls"`) +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. + +If the rule count for the given request is the same in two Routes `A` and +`B`, then the following tiebreaker rules will be applied in the order they +are listed. Route `A` will be selected over `B` if: + +* `A` has only "plain" Host headers and `B` has one or more "wildcard" + host headers +* `A` has more non-Host headers than `B`. +* `A` has at least one "regex" paths and `B` has only "plain" paths. +* `A`'s longest path is longer than `B`'s longest path. +* `A.created_at < B.created_at` + +## 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. + +### 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]. + +### 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]. + +### 3. Proxying and 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: + +- `connect_timeout`: defines in milliseconds the timeout for + establishing a connection to your upstream service. Defaults to `60000`. +- `write_timeout`: defines in milliseconds a timeout between two + successive write operations for transmitting a request to your upstream + service. Defaults to `60000`. +- `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. +- `X-Forwarded-Prefix: `, where `` is the path of the request which + was accepted by Kong. 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 `$request_uri` variable (with + the query string stripped) provided by [`ngx_http_core_module`][ngx-server-port-variable] + will be used. + + {:.note} + > **Note**: Kong returns `"/"` for an empty path, but it doesn't do any other + > normalization on the request path. + +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. + +### 4. Errors and 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. + +### 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]. + +## 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](#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. + +## Configuring TLS for a Route + +Kong provides a way to dynamically serve TLS certificates on a per-connection +basis. TLS 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. + +TLS 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 a TLS certificate on a given Route: first, upload +your TLS 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=*.tls-example.com,other-tls-example.com" +HTTP/1.1 201 Created +... +``` + +The `snis` form parameter is a convenience parameter. Under the hood, it directly inserts an SNI and +associates the uploaded certificate to it. + +Note that one of the SNI names defined in `snis` above contains a wildcard +(`*.tls-example.com`). An SNI may contain a single wildcard in the leftmost (prefix) or +rightmost (suffix) position. This can be useful when maintaining multiple subdomains. A +single `sni` configured with a wildcard name can be used to match multiple +subdomains, instead of creating an SNI for each. + +Valid wildcard positions are `mydomain.*`, `*.mydomain.com`, and `*.www.mydomain.com`. + +A default certificate can be added using the following parameters in Kong configuration: +1. [`ssl_cert`](/gateway/{{page.release}}/reference/configuration/#ssl_cert) +2. [`ssl_cert_key`](/gateway/{{page.release}}/reference/configuration/#ssl_cert_key) + +Or, by dynamically configuring the default certificate with an SNI of `*`: + +```bash +$ curl -i -X POST http://localhost:8001/certificates \ + -F "cert=@/path/to/default-cert.pem" \ + -F "key=@/path/to/default-cert.key" \ + -F "snis=*" +HTTP/1.1 201 Created +... +``` + +Matching of `snis` respects the following priority: + + 1. Exact SNI matching certificate + 2. Search for a certificate by prefix wildcard + 3. Search for a certificate by suffix wildcard + 4. Search for a certificate associated with the SNI `*` + 5. The default certificate on the file system + +You must now register the following Route within Kong. We will match requests +to this Route using only the Host header for convenience: + +```bash +$ curl -i -X POST http://localhost:8001/routes \ + -d 'hosts=prefix.tls-example.com,other-tls-example.com' \ + -d 'service.id=d54da06c-d69f-4910-8896-915c63c270cd' +HTTP/1.1 201 Created +... +``` + +You can now expect the Route to be served over HTTPS by Kong: + +```bash +$ curl -i https://localhost:8443/ \ + -H "Host: prefix.tls-example.com" +HTTP/1.1 200 OK +... +``` + +When establishing the connection and negotiating the TLS handshake, if your +client sends `prefix.tls-example.com` as part of the SNI extension, Kong will serve +the `cert.pem` certificate previously configured. This is the same for both HTTPS and +TLS connections. + +### Restricting the client protocol + +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"`, `"grpc"`, `"grpcs"`, `"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_ TLS termination previously +occurred from a trusted IP. TLS 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 TLS 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"} +``` + +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": "..." + } +} + +``` + +For L4 TLS proxy to work, it is necessary to create route that accepts +the `tls` `protocol`, as well as having the appropriate TLS certificate +uploaded and their `sni` attribute properly set to match incoming connection's +SNI. Please refer to the [Configuring TLS for a Route](#configuring-tls-for-a-route) +section above for instructions on setting this up. + +## 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. + +### 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 TLS, you can accept `wss` only from the +client, but proxy to the upstream service over plain text, or `ws`. + +## Proxy gRPC traffic + +gRPC proxying is natively supported in Kong. In order +to manage gRPC services and proxy gRPC requests with Kong, create Services and +Routes for your gRPC Services (check out the [Configuring a gRPC Service guide][conf-grpc-service]). + +Only observability and logging plugins are supported with +gRPC - plugins known to be supported with gRPC have "grpc" and "grpcs" listed +under the supported protocols field in their Kong Hub page - for example, +check out the [File Log][file-log] plugin's page. + +## Proxy TCP/TLS traffic + +TCP and TLS proxying is natively supported in Kong. + +In this mode, data of incoming connections reaching the `stream_listen` endpoints will +be passed through to the upstream. It is possible to terminate TLS connections +from clients using this mode as well. + +To use this mode, aside from defining `stream_listen`, appropriate Route/Service +object with protocol types of `tcp` or `tls` should be created. + +If TLS termination by Kong is desired, the following conditions must be met: + +1. The Kong port where TLS connection connects to must have the `ssl` flag enabled +2. A certificate/key that can be used for TLS termination must be present inside Kong, + as shown in [Configuring TLS for a Route](#configuring-tls-for-a-route) + +Kong will use the connecting client's TLS SNI server name extension to find +the appropriate TLS certificate to use. + +On the Service side, depends on whether connection between Kong and the upstream +service need to be encrypted, `tcp` or `tls` protocol types can be set accordingly. +This means all of the below setup are supported in this mode: + +1. Client <- TLS -> Kong <- TLS -> Upstream +2. Client <- TLS -> Kong <- Cleartext -> Upstream +3. Client <- Cleartext -> Kong <- TLS -> Upstream + +**Note:** In L4 proxy mode, only plugins that has `tcp` or `tls` in the supported +protocol list are supported. This list can be found in their respective documentation +on the [Kong Plugin Hub](/hub/). + +## 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 TLS 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. + + + +[plugin-configuration-object]: /gateway/{{page.release}}/admin-api#plugin-object +[plugin-development-guide]: /gateway/{{page.release}}/plugin-development +[plugin-association-rules]: /gateway/{{page.release}}/admin-api/#precedence +[proxy-websocket]: /gateway/{{page.release}}/reference/proxy/#proxy-websocket-traffic +[load-balancing-reference]: /gateway/{{page.release}}/reference/loadbalancing +[configuration-reference]: /gateway/{{page.release}}/reference/configuration/ +[configuration-trusted-ips]: /gateway/{{page.release}}/reference/configuration/#trusted_ips +[configuring-a-service]: /gateway/{{page.release}}/get-started/quickstart/configuring-a-service +[API]: /gateway/{{page.release}}/admin-api +[service-entity]: /gateway/{{page.release}}/admin-api/#add-service +[route-entity]: /gateway/{{page.release}}/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 +[conf-grpc-service]: /gateway/{{page.release}}/get-started/quickstart/configuring-a-grpc-service +[file-log]: /hub/kong-inc/file-log diff --git a/app/gateway/2.6.x/reference/rate-limiting.md b/app/gateway/2.6.x/reference/rate-limiting.md new file mode 100644 index 000000000000..6d56f83c7eff --- /dev/null +++ b/app/gateway/2.6.x/reference/rate-limiting.md @@ -0,0 +1,166 @@ +--- +title: Rate Limiting Library +badge: enterprise +--- + +## Overview +This library is designed to provide an efficient, scalable, eventually-consistent sliding window rate limiting library. It relies on atomic operations in shared ngx memory zones to track window counters within a given node, periodically syncing this data to a central data store (current Cassandra, PostgreSQL, and Redis). + +A sliding window rate limiting implementation tracks the number of hits assigned to a specific key (such as an IP address, Consumer, Credential, etc) within a given time window, taking into account previous hit rates to smooth out a calculated rate, while still providing a familiar windowing interface that modern developers are used to (e.g., n hits per second/minute/hour). This is similar to a fixed window implementation, in which request rates reset at the beginning of the window, but without the "reset bump" from which fixed window implementations suffer, while providing a more intuitive interface beyond what leaky bucket or token bucket implementations can offer. Note that we use the term "hit" instead of "request" when referring to incrementing values for rate limit keys, because this library provides an abstract rate limiting interface; a sliding window implementation may have uses outside of HTTP request rate limiting, thus, we describe this library in a more abstract sense. + +A sliding window takes into account a weighted value of the previous window when calculating the current rate for a given key. A window is defined as a period of time, starting at a given "floor" timestamp, where the floor is calculated based on the size of the window. For window sizes of 60 seconds, the floor always falls at the 0th second (e.g., at the beginning of any given minute). Likewise, windows with a size of 30 seconds will begin at the 0th and 30th seconds of each minute. + +Consider a rate limit of 10 hits per minute. In this configuration, this library will calculate the hit rate of a given key based on the number of hits for the current window (starting at the beginning of the current minute), and a weighted percentage of all hits of the previous window (e.g., the previous minute). This weight is calculated based on the current timestamp with respect to the window size in question; the farther away the current time is from the start of the previous window, the lower the weight percentage. This value is best expressed through an example: + +``` +current window rate: 10 +previous window rate: 40 +window size: 60 +window position: 30 (seconds past the start of the current window) +weight = .5 (60 second window size - 30 seconds past the window start) + +rate = 'current rate' + 'previous weight' * 'weight' + = 10 + 40 * ('window size' - 'window position') / 'window size' + = 10 + 40 * (60 - 30) / 60 + = 10 + 40 * .5 + = 30 +``` +Strictly speaking, the formula used to define the weighting percentage is as follows: + +`weight = (window_size - (time() % window_size)) / window_size` + +Where `time()` is the value of the current Unix timestamp. + +Each node in the Kong cluster relies on its own in-memory data store as the source of truth for rate limiting counters. Periodically, each node pushes a counter increment for each key it saw to the cluster, which is expected to atomically apply this diff to the appropriate key. The node then retrieves this key's value from the data store, along with other relevant keys for this data sync cycle. In this manner, each node shares the relevant portions of data with the cluster, while relying on a very high-performance method of tracking data during each request. This cycle of converge -> diverge -> reconverge among nodes in the cluster provides our eventually-consistent model. + +The periodic rate at which nodes converge is configurable; shorter sync intervals will result in less divergence of data points when traffic is spread across multiple nodes in the cluster (e.g., when sitting behind a round robin balancer), whereas longer sync intervals put less r/w pressure on the datastore, and less overhead on each node to calculate diffs and fetch new synced values. The desirable value here depends on use case; when using cluster syncing to refresh nodes periodically (e.g., to inform new cluster nodes of counter data), a value of 10-30 seconds may be desirable, to minimize data store traffic. Contrarily, environments demanding stronger consistency between nodes (such as orchestrated deployments involving a high churn rate among cluster membership, or cases where strict rate limiting policies must be applied to node sitting behind a non-hashing load balancer) should use a lower sync period, on the order of milliseconds. The minimum possible value is 0.001 (1 millisecond), though practically this value is limited by network performance between Kong nodes and the configured data store. + +In addition to periodic data sync behavior, this library can implement rate limiting counter in a synchronous pattern by defining its `sync_rate` as `0`. In such a case, the given counter will be applied directly to the datastore. This behavior is desirable in cases where stronger consistency among the cluster is desired; such a configuration comes with the cost of needing to communicate with the datastore (or Redis) on every request, which can induce noticeable latency into the request ("noticeable" being a relative term of typically a few milliseconds, depending on the performance of the storage mechanism in question; for comparison, Kong typically processes requests on the order of tens of microseconds). + +This library can also forgo syncing counter data entirely, and only apply incremental counters to its local memory zone, by defining a `sync_rate` value of less than `0`. This behavior is useful when cluster-wide syncing of data is unnecessary, such as environments using only a single Kong node, or where Kong nodes live behind a hashing load balancer and are treated as isolated instances. + +Module configuration data, such as sync rate, shared dictionary name, storage policy, etc, is kept in a per-worker public configuration table. Multiple configurations can be defined as stored as arbitrary `namespaces` (more on this below). + +## Developer Notes +### Public Functions +The following public functions are provided by this library: + +`ratelimiting.new` + +Syntax: +``` +ok = ratelimiting.new(opts) +``` + +Define configurations for a new namespace. The following options are accepted: + +- `dict`: Name of the shared dictionary to use +- `sync_rate`: Rate, in seconds, to sync data diffs to the storage server. +- `strategy`: Storage strategy to use. Currently `cassandra`, `postgres`, and `redis` are supported. Strategies must provide several public—functions defined below. +- `strategy_opts`: A table of options used by the storage strategy. Currently only applicable for the `redis` strategy. +- `namespace`: String defining these config values. A namespace may only be defined once; if a namespace has already been defined on this worker, an error is thrown. If no namespace is defined, the literal string "default" will be used. +- `window_sizes`: A list of window sizes used by this configuration. + +`ratelimiting.increment` + +Syntax: +``` +rate = ratelimiting.increment(key, window_size, value, namespace?) +``` + +Increment a given key for `window_size` by value. If namespace is undefined, the "default" namespace is used. value can be any number Lua type (but ensure that the storage strategy in use for this namespace can support decimal values if a non-integer value is provided). This function returns the sliding rate for this key/window size after the increment of value has been applied. + +`ratelimit.sliding_window` + +Syntax: +``` +rate = ratelimit.sliding_window(key, window_size, cur_diff?, namespace?) +``` + +Return the current sliding rate for this key/window size. An optional `cur_diff` value can be provided that overrides the current stored diff for this key. If `namespace` is undefined, the "default" namespace is used. + +`ratelimiting.sync` + +Syntax: +``` +ratelimiting.sync(premature, namespace?) +``` + +Sync all currently stored key diffs in this worker with the storage server, and retrieve the newly synced value. If namespace is undefined, the "default" `namespace` is used. Before the diffs are pushed, another sync call for the given namespace is scheduled at `sync_rate` seconds in the future. Given this, this function should typically be called during the `init_worker` phase to initialize the recurring timer. This function is intended to be called in an `ngx.timer` context; hence, the first variable represents the injected `premature` param. + +`ratelimiting.fetch` + +Syntax: +``` +ratelimiting.fetch(premature, namespace, time, timeout?) +``` + +Retrieve all relevant counters for the given namespace at the given time. This +function establishes a shm mutex such that only one worker will fetch and +populate the shm per execution. If timeout is defined, the mutex will expire +based on the given timeout value; otherwise, the mutex is unlocked immediately +following the dictionary update. This function can be called in an `ngx.timer` +context; hence, the first variable represents the injected `premature` param. + +### Strategy Functions + +Storage strategies must provide the following interfaces: + +#### strategy_class.new + +Syntax: +``` +strategy = strategy_class.new(dao_factory, opts) +``` + +Implement a new strategy object. `opts` is expected to be a table type, and can be used to pass opaque/arbitrary options to the strategy class. + +#### strategy:push_diffs + +Syntax: +``` +strategy:push_diffs(diffs) +``` + +Push a table of key diffs to the storage server. diffs is a table provided in the following format: + +``` +[1] = { + key = "1.2.3.4", + windows = { + { + window = 12345610, + size = 60, + diff = 5, + namespace = foo, + }, + { + window = 12345670, + size = 60, + diff = 5, + namespace = foo, + }, + } + }, + ... + ["1.2.3.4"] = 1, + ... + ``` + +#### strategy:get_counters + +Syntax: +``` +rows = strategy:get_counters(namespace, window_sizes, time?) +``` + +Return an iterator for each key stored in the datastore/redis for a given `namepsace` and list of window sizes. 'time' is an optional unix second- precision timestamp; if not provided, this value will be set via `ngx.time()`. It is encouraged to pass this via a previous defined timestamp, depending on the context (e.g., if previous calls in the same thread took a nontrivial amount of time to run). + +#### strategy:get_window + +Syntax: +``` +window = strategy:get_window(key, namespace, window_start, window_size) +``` + +Retrieve a single key from the data store based on the values provided. diff --git a/app/gateway/2.6.x/statsd.rules.yaml b/app/gateway/2.6.x/statsd.rules.yaml new file mode 100644 index 000000000000..d5bdcc664e26 --- /dev/null +++ b/app/gateway/2.6.x/statsd.rules.yaml @@ -0,0 +1,82 @@ +mappings: +# by Service +- match: kong.service.*.request.count + name: "kong_requests_proxy" + labels: + job: "kong_metrics" + +- match: kong.service.*.status.* + name: "kong_status_code" + labels: + service: "$1" + status_code: $2 + job: "kong_metrics" + +- match: kong.service.*.kong_latency + name: "kong_latency_proxy_request" + timer_type: histogram + buckets: [1] + min_max: true + labels: + job: "kong_metrics" + +- match: kong.service.*.upstream_latency + name: "kong_latency_upstream" + timer_type: histogram + buckets: [1] + min_max: true + labels: + job: "kong_metrics" + +- match: kong.service.*.cache_datastore_hits_total + name: "kong_cache_datastore_hits_total" + labels: + job: "kong_metrics" + +- match: kong.service.*.cache_datastore_misses_total + name: "kong_cache_datastore_misses_total" + labels: + job: "kong_metrics" + +# by Service and Route +- match: kong.service.*.user.*.status.* + name: "kong_status_code_per_consumer" + labels: + service: "$1" + route_id: "" + consumer: "$2" + status_code: $3 + job: "kong_metrics" + +- match: kong.route.*.user.*.status.* + name: "kong_status_code_per_consumer" + labels: + service: "" + route_id: "$1" + consumer: "$2" + status_code: $3 + job: "kong_metrics" + +# by Service and Workspace +- match: kong.service.*.workspace.*.status.* + name: "kong_status_code_per_workspace" + labels: + service: "$1" + workspace: "$2" + status_code: $3 + job: "kong_metrics" + +# by node +- match: kong.node.*.shdict.*.free_space + name: "kong_shdict_free_space" + labels: + node: "$1" + shdict: "$2" + job: "kong_metrics" + +- match: kong.node.*.shdict.*.capacity + name: "kong_shdict_capacity" + labels: + node: "$1" + shdict: "$2" + job: "kong_metrics" diff --git a/app/gateway/2.6.x/vitals/index.md b/app/gateway/2.6.x/vitals/index.md new file mode 100644 index 000000000000..f87fed039c23 --- /dev/null +++ b/app/gateway/2.6.x/vitals/index.md @@ -0,0 +1,90 @@ +--- +title: Vitals Overview +badge: enterprise +--- + +Use Kong Vitals (Vitals) to monitor {{site.ee_product_name}} health and performance, and to understand the microservice API transactions traversing Kong. Vitals uses visual API analytics to see exactly how your APIs and Gateway are performing. Quickly access key statistics, monitor vital signs, and pinpoint anomalies in real time. + +* Use Kong Admin API to access Vitals data via endpoints. Additional visualizations, including dashboarding of Vitals data alongside data from other systems, can be achieved using the Vitals API to integrate with common monitoring systems. + +* Use Kong Manager to view visualizations of Vitals data, including the Workspaces Overview Dashboard, Workspace Charts, Vitals tab, and Status Codes, and to generate CSV Reports. + +![Vitals Overview](/assets/images/products/gateway/vitals/vitals_overview.png) + +## Prerequisites +Vitals is enabled by default in {{site.ee_product_name}} and available upon the first login of a Super Admin. + +You will need one of the following databases to use Vitals: +* InfluxDB +* PostgreSQL 9.5+ +* Cassandra 2.1+ + +## Guidelines for viewing Vitals +When using Vitals, note: +* Vitals is enabled by default and accessible the first time a Super Admin logs in. + * To enable or disable Vitals, see [Enable or Disable Vitals](#enable-or-disable-vitals). +* Any authorized user can view Vitals for the entire Kong cluster or for a particular Workspace. + * If a user does not have access to a Workspace, its Vitals are hidden from view. + * If a user does not have access to Vitals data, charts will not display. + +## Vitals API +Vitals data is available via endpoints on Kong’s Admin API. Access to these endpoints may be controlled via Admin API RBAC. The Vitals API is described in the OAS (Open API Spec, formerly Swagger) file. See a sample here (downloadable file): [`vitalsSpec.yaml`](/gateway/{{page.release}}/vitals/vitalsSpec.yaml). + +## Viewing Vitals in Kong Manager +View Vitals information in Kong Manager using any of the following: +* Overview Dashboard, available from the Workspaces page for an overview of your Kong cluster, or an individual Workspace for an overview of the selected Workspace. +* Workspace charts, which display on the Workspaces page beneath the Overview Dashboard. These charts give a quick overview of the status of an individual Workspace. +* Vitals tab, which provides detailed information about your Kong cluster, including total requests, latency, and cache information. +* Status Codes to view cluster-wide status code classes. + +## Overview Dashboard +When you log in to Kong Manager, the Workspaces page displays by default. The top of the page displays the Vitals Overview Dashboard summarizing your Kong cluster, including the health and performance of your APIs and Gateway, total requests, average error rate, total consumers, and total services. This Vitals Overview Dashboard makes it easy for an Admin to quickly identify any issues that need attention. + +## Workspace charts +On the Workspaces page, beneath the Overview Dashboard, the Workspaces section displays each Workspace with a chart showing Vitals for the most recently added services, consumers, and plugins for that Workspace. Hover over a coordinate to view the exact number of successes and errors at a given timestamp, or drilldown into the Workspace chart for more details. + +## Vitals tab +The Vitals tab, or Vitals view, displays metrics about the health and performance of Kong nodes and Kong-proxied APIs. The Vitals View displays total requests, latency, and cache information. You also can generate reports from the Vitals view. + +Options to populate the Vitals view, or areas in the chart, include: + +| Option | Description | +|--------------------------|----------------------------------------------------------------------------------------------| +| Timeframe Selector | A timeframe selector controls the timeframe of data visualized, which indirectly controls the granularity of the data. For example, the “Last 5 Minutes” selection displays 1-second resolution data, while longer time frames display 1-minute resolution data. +| View | Select to populate the Vitals chart by Hostname, Hostname + ID, or ID.| +| Total Requests | The Total Requests chart displays a count of all proxy requests received. This includes requests that were rejected due to rate-limiting, failed authentication, and so on.| +| Cluster and Node Data | Metrics are displayed on Vitals charts at both node and cluster level. Controls are available to show cluster-wide metrics and/or node-specific metrics. Clicking on individual nodes will toggle the display of data from those nodes. Nodes are identified by a unique Kong node identifier, by hostname, or by a combination of the two.| + +## Status Codes +The Status Codes view displays visualizations of cluster-wide status code classes (1xx, 2xx, 3xx, 4xx, 5xx). The Status Codes view contains the counts of status code classes graphed over time, as well as the ratio of code classes to total requests. See [Status Codes](/gateway/{{page.release}}/vitals/vitals-metrics/#status-code). + +>**Note**: The Status Codes view does not include non-standard code classes (6xx, 7xx, etc.). Individual status code data can be viewed in the Consumer, Route, and Service details pages under the Activity tab. Both standard and non-standard status codes are visible in these views. + +## Enable or disable Vitals +{{site.ee_product_name}} ships with Vitals enabled by default. To enable or disable Vitals, edit the configuration file or environment variables. + +{% navtabs %} +{% navtab Using kong.conf %} + +1. Edit the configuration file to enable or disable Vitals: + ```bash + # via your Kong configuration file; e.g., kong.conf + $ vitals = on # vitals is enabled + $ vitals = off # vitals is disabled + ``` +2. Restart Kong. + +{% endnavtab %} +{% navtab Using environment variables %} + +1. Use environment variables to enable or disable Vitals: + ```bash + # or via environment variables + $ export KONG_VITALS=on + $ export KONG_VITALS=off + ``` + +2. Restart Kong. + +{% endnavtab %} +{% endnavtabs %} diff --git a/app/gateway/2.6.x/vitals/vitals-influx-strategy.md b/app/gateway/2.6.x/vitals/vitals-influx-strategy.md new file mode 100644 index 000000000000..64aca4113408 --- /dev/null +++ b/app/gateway/2.6.x/vitals/vitals-influx-strategy.md @@ -0,0 +1,286 @@ +--- +title: Vitals with InfluxDB +badge: enterprise +--- + +Leveraging a time series database for Vitals data +can improve request and Vitals performance in very-high traffic {{site.ee_product_name}} +clusters (such as environments handling tens or hundreds of thousands of +requests per second), without placing additional write load on the database +backing the Kong cluster. + +For information about using Kong Vitals with a database as the backend (for example, +PostgreSQL, Cassandra), refer to +[Kong Vitals](/gateway/{{page.release}}/vitals/). + +## Set up Kong Vitals with InfluxDB + +### Install {{site.base_gateway}} + +If you already have a {{site.base_gateway}} instance, skip to [deploying a license](#deploy-a-kong-gateway-license). + +If you have not installed {{site.base_gateway}}, a Docker installation +will work for the purposes of this guide. + + +### Pull the {{site.base_gateway}} Docker image {#pull-image} + +1. Pull the following Docker image. + + ```bash + docker pull kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine + ``` + + {:.important} + > Some [older {{site.base_gateway}} images](https://support.konghq.com/support/s/article/Downloading-older-Kong-versions) + are not publicly accessible. If you need a specific patch version and can't + find it on [Kong's public Docker Hub page](https://hub.docker.com/r/kong/kong-gateway), contact + [Kong Support](https://support.konghq.com/). + + You should now have your {{site.base_gateway}} image locally. + +1. Tag the image. + + ```bash + docker tag kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine kong-ee + ``` + + +### Start the database and {{site.base_gateway}} containers + +1. Create a custom network to allow the containers to discover and communicate +with each other. + + ```bash + docker network create kong-ee-net + ``` + +1. Start a PostgreSQL container: + + ```p + docker run -d --name kong-ee-database \ + --network=kong-ee-net \ + -p 5432:5432 \ + -e "POSTGRES_USER=kong" \ + -e "POSTGRES_DB=kong" \ + -e "POSTGRES_PASSWORD=kong" \ + postgres:9.6 + ``` + +1. Prepare the Kong database: + + ```sh + docker run --rm --network=kong-ee-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=kong" \ + -e "KONG_PASSWORD=kongpass" \ + kong-ee kong migrations bootstrap + ``` + + +1. Start the gateway with Kong Manager: + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + + ```sh + docker run -d --name kong-ee --network=kong-ee-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=kong" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \ + -e "KONG_ADMIN_GUI_URL=http://localhost:8002" \ + -e "KONG_VITALS_STRATEGY=influxdb" \ + -e "KONG_VITALS_TSDB_ADDRESS=influxdb:8086" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 8001:8001 \ + -p 8444:8444 \ + -p 8002:8002 \ + -p 8445:8445 \ + -p 8003:8003 \ + -p 8004:8004 \ + kong-ee + ``` + + {:.note} + > **Note:** For `KONG_ADMIN_GUI_URL`, replace `localhost` + with the DNS name or IP of the Docker host. `KONG_ADMIN_GUI_URL` + _should_ have a protocol, for example, `http://`. + +### Deploy a {{site.base_gateway}} license + +If you already have a {{site.ee_product_name}} license attached to your {{site.base_gateway}} +instance, skip to [starting an InfluxDB database](#start-an-influxdb-database). + +You will not be able to access the Kong Vitals functionality without a valid +{{site.ee_product_name}} license attached to your {{site.base_gateway}} instance. + +{% include_cached /md/enterprise/deploy-license.md heading="####" release=page.release %} + +### Start an InfluxDB database + +Production-ready InfluxDB installations should be deployed as a separate +effort, but for proof-of-concept testing, running a local InfluxDB instance +is possible with Docker: + +```bash +$ docker run -p 8086:8086 \ + --network= \ + --name influxdb \ + -e INFLUXDB_DB=kong \ + influxdb:1.8.4-alpine +``` + +{:.warning} +> You **must** use InfluxDB 1.8.4-alpine because +InfluxDB 2.0 will **not** work. + +Writing Vitals data to InfluxDB requires that the `kong` database is created, +this is done using the `INFLUXDB_DB` variable. + +### Configure {{site.base_gateway}} + +{:.note} +> **Note:** If you used the configuration in +[Installing {{site.base_gateway}} on Docker](#install-kong-gateway), +then you do not need to complete this step. + +In addition to enabling Kong Vitals, {{site.base_gateway}} must be configured to use InfluxDB as the +backing strategy for Vitals. The InfluxDB host and port must also be defined: + +```bash +$ echo "KONG_VITALS_STRATEGY=influxdb KONG_VITALS_TSDB_ADDRESS=influxdb:8086 kong reload exit" \ +| docker exec -i kong-ee /bin/sh +``` + +{:.note} +> **Note**: In Hybrid Mode, configure [`vitals_strategy`](/gateway/{{page.release}}/reference/configuration/#vitals_strategy) +and [`vitals_tsdb_address`](/gateway/{{page.release}}/reference/configuration/#vitals_tsdb_address) +on both the control plane and all data planes. + +## Understanding Vitals data using InfluxDB measurements + +Kong Vitals records metrics in two InfluxDB measurements: + +1. `kong_request`: Contains field values for request latencies and HTTP, + and tags for various Kong entities associated with the requests (for + example, the Route and Service in question). +2. `kong_datastore_cache`: Contains points about cache hits and + misses. + +To display the measurement schemas on your InfluxDB instance running +in Docker: + +1. Open command line in your InfluxDB Docker container. + + ```sh + $ docker exec -it influxdb /bin/sh + ``` + +2. Log in to the InfluxDB CLI. + + ```sh + $ influx -precision rfc3339 + ``` + +3. Enter the InfluxQL query for returning a list of tag keys associated +with the specified database. + + ```sql + > SHOW TAG KEYS ON kong + ``` + + Example result: + + ```sql + name: kong_request + tagKey + ------ + consumer + hostname + route + service + status_f + wid + workspace + + name: kong_datastore_cache + tagKey + ------ + hostname + wid + ``` + +4. Enter the InfluxQL query for returning the field keys and the +data type of their field values. + + ```sh + > SHOW FIELD KEYS ON kong + ``` + + Example result: + + ```sql + name: kong_request + fieldKey fieldType + -------- --------- + kong_latency integer + proxy_latency integer + request_latency integer + status integer + + name: kong_datastore_cache + fieldKey fieldType + -------- --------- + + hits integer + misses integer + ``` + +The tag `wid` is used to differentiate the unique worker ID per host, to avoid +duplicate metrics shipped at the same point in time. + +As demonstrated above, the series cardinality of the `kong_request` measurement +varies based on the cardinality of the Kong cluster configuration - a greater +number of Service/Route/Consumer/Workspace combinations handled by Kong results +in a greater series cardinality as written by Vitals. + +## Sizing an InfluxDB node/cluster for Vitals + +Consult the +[InfluxDB sizing guidelines](https://docs.influxdata.com/influxdb/v1.8/guides/hardware_sizing/) +for reference on appropriately sizing an InfluxDB node/cluster. + +{:.note} +> **Note:** The query behavior when reading Vitals data falls under the "moderate" load +category as defined by the InfluxDB sizing guidelines. Several `GROUP BY` statements and +functions are used to generate the Vitals API responses, which can require +significant CPU resources to execute when hundreds of thousands or millions of +data points are present. + +## Query frequency and precision + +Kong buffers Vitals metrics and writes InfluxDB points in batches to improve +throughput in InfluxDB and reduce overhead in the Kong proxy path. Each Kong +worker process flushes its buffer of metrics every 5 seconds or 5000 data points, +whichever comes first. + +Metrics points are written with microsecond (`u`) precision. To comply with +the [Vitals API](/gateway/{{page.release}}/vitals/vitalsSpec.yaml), measurement +values are read back grouped by second. + +{:.note} +> **Note:** Because of limitations in the OpenResty API, writing values with +microsecond precision requires an additional syscall per request. + +## Managing the retention policy of the Kong database + +Vitals InfluxDB data points are not downsampled or managed by a +retention policy through Kong. InfluxDB operators are encouraged to manually manage +the retention policy of the `kong` database to reduce the disk space and memory +needed to manage Vitals data points. diff --git a/app/gateway/2.6.x/vitals/vitals-metrics.md b/app/gateway/2.6.x/vitals/vitals-metrics.md new file mode 100644 index 000000000000..99edb5dca20a --- /dev/null +++ b/app/gateway/2.6.x/vitals/vitals-metrics.md @@ -0,0 +1,113 @@ +--- +title: Vitals Metrics +badge: enterprise +--- + +Vitals metrics fall into two categories: +* Health Metrics — for monitoring the health of a Kong cluster +* Traffic Metrics — for monitoring the usage of upstream services + + +All metrics are collected at 1-second intervals and aggregated into 1-minute +intervals. The 1-second intervals are retained for one hour. The 1-minute +intervals are retained for 25 hours. + +If longer retention times are needed, the Vitals API can be used to pull metrics +out of Kong and into a data retention tool. + +## Health Metrics + +Health metrics give insight into the performance of a Kong cluster; for example, +how many requests the cluster is processing and the latency on those requests. + +Health metrics are tracked for each node in a cluster as well as for the cluster +as a whole. In Kong, a node is a running process with a unique identifier, +configuration, cache layout, and connections to both Kong’s datastores and the +upstream APIs it proxies. Note that node identifiers are unique to the process, +and not to the host on which the process runs. In other words, each Kong restart +results in a new node, and therefore a new node ID. + +### Latency + +The Vitals API may return null for Latency metrics. This occurs when no API +requests were proxied during the timeframe. Null latencies are not graphed in +Kong Manager; periods with null latencies appear as gaps in Vitals charts. + +#### Proxy Latency (Request) + +The Proxy Latency metrics are the min, max, and average values for the time, in milliseconds, that the Kong proxy spends processing API proxy requests. This includes time to execute plugins that run in the access phase and the DNS lookup time. This does not include time spent in Kong’s load balancer, time spent sending the request to the upstream, or time spent on the response. + +These metrics are referenced in the Vitals API with the following labels: `latency_proxy_request_min_ms`, `latency_proxy_request_max_ms`, `latency_proxy_request_avg_ms`. + +Latency is not reported when a request is prematurely ended by Kong (e.g., bad auth, rate limited, etc.). Note that this differs from the **Total Requests** metric that does count such requests. + +#### Upstream Latency + +The Upstream Latency metrics are the min, max, and average values for the time elapsed, in milliseconds, between Kong sending requests upstream and Kong receiving the first bytes of responses from upstream. + +These metrics are referenced in the Vitals API with the following labels: `latency_upstream_min_ms`, `latency_upstream_max_ms`, `latency_upstream_avg_ms`. + +### Datastore Cache + +#### Datastore Cache Hit/Miss + +The Datastore Cache Hit/Miss metrics are the count of requests to Kong's node-level datastore cache. When Kong workers need configuration information to respond to a given API proxy request, they first check their worker-specific cache (also known as L1 cache), then if the information isn’t available they check the node-wide datastore cache (also known as L2 cache). If neither cache contains the necessary information, Kong requests it from the datastore. + +A `Hit` indicates that an entity was retrieved from the data store cache. A `Miss` indicates that the record had to be fetched from the datastore. Not every API request will result in datastore cache access; some entities will be retrieved from Kong's worker-specific cache memory. + +These metrics are referenced in the Vitals API with the following labels: `cache_datastore_hits_total`, `cache_datastore_misses_total`. + +#### Datastore Cache Hit Ratio + +This metric contains the ratio of datastore cache hits to the total count of datastore cache requests. + +> **Note:** Datastore Cache Hit Ratio cannot be calculated for time indices with no hits and no misses. + +## Traffic Metrics + +Traffic metrics provide insight into which of your services are being used, who is using them, and how they are responding. + +### Request Counts + +#### Total Requests + + +This metric is the count of all API proxy requests received. This includes requests that were rejected due to rate-limiting, failed authentication, etc. + +This metric is referenced in the Vitals API with the following label: `requests_proxy_total`. + +#### Requests Per Consumer + +This metric is the count of all API proxy requests received from each specific consumer. Consumers are identified by credentials in their requests (e.g., API key, OAuth token) as required by the Kong Auth plugins in use. + +This metric is referenced in the Vitals API with the following label: `requests_consumer_total`. + +### Status Codes + +#### Total Status Code Classes + +This metric is the count of all status codes grouped by status code class (e.g. 4xx, 5xx). + +This metric is referenced in the Vitals API with the following label: `status_code_classes_total`. + +#### Total Status Codes per Service + +This metric is the total count of each specific status code for a given service. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_service_total`. + +#### Total Status Codes per Route + +This metric is the total count of each specific status code for a given route. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_route_total`. + +#### Total Status Codes per Consumer +This metric is the total count of each specific status code for a given consumer. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_consumer_total`. + +#### Total Status Codes per Consumer Per Route +This metric is the total count of each specific status code for a given consumer and route. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_consumer_route_total`. diff --git a/app/gateway/2.6.x/vitals/vitals-prometheus-strategy.md b/app/gateway/2.6.x/vitals/vitals-prometheus-strategy.md new file mode 100644 index 000000000000..a82d073e8335 --- /dev/null +++ b/app/gateway/2.6.x/vitals/vitals-prometheus-strategy.md @@ -0,0 +1,300 @@ +--- +title: Vitals with Prometheus +badge: enterprise +--- + +This document covers integrating Kong Vitals with a new or existing Prometheus +time-series server or cluster. Leveraging a time-series database for Vitals data +can improve request and Vitals performance in very-high traffic {{site.base_gateway}} +clusters (such as environments handling tens or hundreds of thousands of +requests per second), without placing addition write load on the database +backing the Kong cluster. + +For using Vitals with a database as the backend (i.e. PostgreSQL, Cassandra), +refer to [Kong Vitals](/gateway/{{page.release}}/vitals/). + +## Lifecycle Overview + +Kong Vitals integrates with Prometheus using an intermediary data exporter, the [Prometheus StatsD exporter](https://github.com/prometheus/statsd_exporter). +This integration allows Kong to efficiently ship Vitals metrics to an outside process where data points +can be aggregated and made available for consumption by Prometheus, without impeding performance +within the Kong proxy itself. In this design, Kong writes Vitals metrics to the StatsD exporter +as [StatsD metrics](https://github.com/statsd/statsd/blob/master/docs/metric_types.md). Prometheus +scrapes this exporter as it would any other endpoint. Kong then queries Prometheus to retrieve and +display Vitals data via the API and Kong Manager. Prometheus does not ever directly scrape the Kong +nodes for time series data. A trivialized workflow looks as follows: + +![Single Node Example Data Flow](/assets/images/products/gateway/vitals/prometheus-single.png) + +It is not uncommon to separate Kong functionality amongst a cluster of nodes. For example, +one or more nodes serve only proxy traffic, while another node is responsible for serving the +Kong Admin API and Kong Manager. In this case, the node responsible for proxy traffic writes +the data to a StatsD exporter, and the node responsible for Admin API reads from Prometheus: + +![Multi Node Example Data Flow](/assets/images/products/gateway/vitals/prometheus-read-write.png) + +In either case, the StatsD exporter process can be run either as a standalone process/container +or as a sidecar/adjacent process within a VM. Note that in high-traffic environments, data aggregation +within the StatsD exporter process can cause significant CPU usage. In such cases, we recommend to +run Kong and StatsD processes on separate hardware/VM/container environments to avoid saturating CPU usage. + +## Set up Prometheus environment for Vitals + +### Download Prometheus + +The latest release of Prometheus can be found at the [Prometheus download page](https://prometheus.io/download/#prometheus). + +Prometheus should be running on a separate node from the one running Kong. +For users that are already using Prometheus in their infrastructure, it's +possible to use existing Prometheus nodes as Vitals storage backend. + +In this guide, we assume Prometheus is running on hostname `prometheus-node` +using default config that listens on port `9090`. + +### Download and configure StatsD exporter + +StatsD exporter is distributed as a Docker image. Pull the latest version +with the following command: + +```sh +docker pull kong/statsd-exporter-advanced:0.3.1 +``` + +The binary includes features like min/max gauges and Unix domain +socket support which are not supported in the public project. + +{:.important} +> This Docker image is a Kong fork of the Prometheus community project and the mapping rules linked below +> do not work with the public image. Ensure you are using the correct one. +> +> If you prefer to use the Prometheus community Helm chart to deploy the exporter, override the image +> and tag in the `values` file as shown below: +> +> ```yaml +> image: +> repository: kong/statsd-exporter-advanced +> tag: 0.3.1 +> ``` + +StatsD exporter needed to configured with a set of mapping rules to translate +the StatsD UDP events to Prometheus metrics. A default set of mapping rules can +be downloaded at +[statsd.rules.yaml](/gateway/{{page.release}}/statsd.rules.yaml). +Then start StatsD exporter with + +```bash +./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.listen-unixgram='' +``` + +The StatsD mapping rules file must be configured to match the metrics sent from +Kong. To learn how to customize the StatsD events name, please refer to +[Enable Vitals with Prometheus strategy in Kong](#enable-vitals-with-prometheus-strategy-in-kong) +section. + +StatsD exporter can run either on a separate node from Kong (to avoid resource +competition with Kong), or on the same host with Kong (to reduce unnecessary +network overhead). + +In this guide, we assume StatsD exporter is running on hostname `statsd-node`, +using default config that listens to UDP traffic on port `9125` and the metrics +in Prometheus Exposition Format are exposed on port `9102`. + +### Configure Prometheus to scrape StatsD exporter + +To configure Prometheus to scrape StatsD exporter, add the following section to +`scrape_configs` in `prometheus.yaml`. + +```yaml +scrape_configs: + - job_name: 'vitals_statsd_exporter' + scrape_interval: "5s" + static_configs: + - targets: ['statsd-node:9102'] +``` + +Please update `statsd-node` with the actual hostname that runs StatsD exporter. + +If you are using service discovery, it will be more convenient to configure +multiple StatsD exporters in Prometheus. Please refer to the +[`scape_configs`](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Cscrape_config%3E) +section of Prometheus document for further reading. + +By default, the Vitals graph in Kong Manager uses the configured target address +in the legend, which is named `instance` in the Prometheus metrics label. For some service +discovery setups where `instance` is `IP:PORT`, the user might want to relabel the `instance` +label to display a more meaningful hostname in the legend. +To do so, the user can also refer to the [`scape_configs`](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Cscrape_config%3E) +section and rewrite the `instance` label with the corresponding meta label. + +For example, in a Kubernetes environment, use the following relabel rules: + +```yaml +scrape_configs: + - job_name: 'vitals_statsd_exporter' + kubernetes_sd_configs: + # your SD config to filter statsd exporter pods + relabel_configs: + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: 'instance' +``` + +### Enable Vitals with Prometheus strategy in Kong + +You can change this in your configuration to enable Vitals with Prometheus: + +```bash +# via your Kong configuration file +vitals = on +vitals_strategy = prometheus +vitals_statsd_address = statsd-node:9125 +vitals_tsdb_address = prometheus-node:9090 +``` + +```bash +# or via environment variables +export KONG_VITALS=on +export KONG_VITALS_STRATEGY=prometheus +export KONG_VITALS_STATSD_ADDRESS=statsd-node:9125 +export KONG_VITALS_TSDB_ADDRESS=prometheus-node:9090 +``` + +{:.note} +> **Note**: In Hybrid Mode, configure [`vitals_strategy`](/gateway/{{page.release}}/reference/configuration/#vitals_strategy) +and [`vitals_tsdb_address`](/gateway/{{page.release}}/reference/configuration/#vitals_tsdb_address) +on both the control plane and all data planes. + +Please update `statsd-node` and `prometheus-node` with the actual hostname that +runs StatsD exporter and Prometheus. + +As with other Kong configurations, your changes take effect on `kong reload` or +`kong restart`. + +If you set `scrape_interval` in Prometheus other than the default value of `5` +seconds, you will also need to update the following: + +```bash +# via your Kong configuration file +vitals_prometheus_scrape_interval = new_value_in_seconds +``` + +```bash +# or via environment variables +export KONG_VITALS_PROMETHEUS_SCRAPE_INTERVAL=new_value_in_seconds +``` + +The above option configures `interval` parameter when querying Prometheus. +The value `new_value_in_seconds` should be equal or larger than +`scrape_interval` config in Prometheus. + +You can also configure Kong to send StatsD events with a different prefix from +the default value of `kong`. Make sure the prefix in statsd.rules +is same as that in Kong configuration: + +```bash +# via your Kong configuration file +vitals_statsd_prefix = kong-vitals +``` + +```bash +# or via environment variables +export KONG_VITALS_STATSD_PREFIX=kong-vitals +``` + +```yaml +# in statsd.rules +mappings: +# by API +- match: kong-vitals.api.*.request.count + name: "kong_requests_proxy" + labels: + job: "kong_metrics" +# follows other metrics +# ... +``` + +### Install Grafana dashboard + +If you use Grafana, you can import the Kong Vitals Prometheus dashboard to visualize the data. + +In your Grafana installation, click the **+** button in the sidebar, and choose **Import**. + +On the **Import** screen, find the **Grafana.com Dashboard** field and enter `11870`. Then, click **Load**. Optionally, you +can also download the JSON model from [https://grafana.com/grafana/dashboards/11870](https://grafana.com/grafana/dashboards/11870) and import it manually. + +On the next screen, select the **Prometheus** data source that is configured to scrape `statsd-exporter`, then +click **Import**. + +## Tuning and Optimization + +### StatsD exporter UDP buffer + +As the amount of concurrent requests increases, the length of the queue to store +unprocessed UDP events will grow as well. +It's necessary to increase the UDP read buffer size to avoid possible packet +dropping. + +To increase the UDP read buffer for the StatsD exporter process, run the binary +using the following example to set read buffer to around 3 MB: + +``` +./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.listen-unixgram='' \ + --statsd.read-buffer=30000000 +``` + +To increase the UDP read buffer for the host that's running, adding the +following example line to `/etc/sysctl.conf`: + +``` +net.core.rmem_max = 60000000 +``` + +And then apply the setting with root privilege: + +``` +# sysctl -p +``` + +### StatsD exporter with Unix domain socket + +It is possible to further reduce network overhead by deploying StatsD exporter +on the same node with Kong and let the exporter listen on local Unix domain +socket. + +```bash +./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.read-buffer=30000000 \ + --statsd.listen-unixgram='/tmp/statsd.sock' +``` + +By default the socket is created with permission `0755`, so that StatsD exporter + has to be running with the same user with Kong to allow Kong to write UDP + packets to the socket. To allow the exporter and Kong to run as different + users, the socket can be created with permission `0777` with the following: + +```bash +./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.read-buffer=30000000 \ + --statsd.listen-unixgram='/tmp/statsd.sock' \ + --statsd.unixsocket-umask="777" +``` + +## Exported Metrics + +With the above configuration, the Prometheus StatsD exporter will make available all +metrics as provided by the [standard Vitals configuration](/gateway/{{page.release}}/vitals/vitalsSpec.yaml). + +Additionally, the exporter process provides access to the default metrics exposed by the [Golang +Prometheus client library](https://prometheus.io/docs/guides/go-application/). These metric names +include the `go_` and `process_` prefixes. These data points are related specifically +to the StatsD exporter process itself, not Kong. Infrastructure teams may find this data +useful, but they are of limited value with respect to monitoring Kong behavior. + +## Accessing Vitals metrics from Prometheus + +You can also access Kong Vitals metrics in Prometheus and display on Grafana +or setup alerting rules. With the example StatsD mapping rules, all metrics are +labeled with `exported_job=kong_vitals`. With the above Prometheus scrape config +above, all metrics are also labeled with `job=vitals_statsd_exporter`. diff --git a/app/gateway/2.6.x/vitals/vitals-reports.md b/app/gateway/2.6.x/vitals/vitals-reports.md new file mode 100644 index 000000000000..77eb8d05158e --- /dev/null +++ b/app/gateway/2.6.x/vitals/vitals-reports.md @@ -0,0 +1,49 @@ +--- +title: Vitals Reports +badge: enterprise +--- + +Browse, filter, and view your data in a Vitals time-series report, and export the data into a comma-separated values (CSV) file. + +When generating a Vitals report, you can: +* Generate a report across all Workspaces or a single Workspace. +* Filter report parameters, such as object, metric, metric type, and values. +* Select the time period or interval for the report, such as minutes, hours, or days. +* View a line chart that automatically generates depending on the selected criteria. +* Export your report to a CSV file. + + +## Prerequisites + +InfluxDB database installed and configured. For more information, see +[Vitals with InfluxDB](/gateway/{{page.release}}/vitals/vitals-influx-strategy/). + +**Important**: The Vitals Reports feature is not compatible with a PostgreSQL or Cassandra database. If using one of these databases, the Reports button will not display on the Vitals view. + + +## Generate a Vitals Report + +To create a time-series report containing Vitals data, complete the steps in this section. + +1. On the Vitals view, click the **Reports** button. + +2. On the Reports page select the **Timeframe**, up to 12 hours, for which you want to create the report. + +3. Select the report criteria for the report: + + | Selection | Description | + |--------------------------|----------------------------------------------------------------------------------------------| + | *Report Type* | Consumer Requests: This report is for requests made by Consumers.
    Service Requests: This report is for services with a Service ID and name of the service that is stored in the {{site.base_gateway}} database.
    Cluster Latency: This report is the aggregation of two fields. | + | *Scope* | Drill down and filter for more detailed information. | + | *Interval* | Select the time interval to display in the report: weeks, hours, days, minutes. If you select an interval that is out of the available range, the results return zeroes. | + + +4. A Vitals report generates, starting with a summary of data in your report, including Id, Name, App Name, App Id, and Total. Note that the App Name and App Id are dependent on the Dev Portal App Registration plugin. For more information about status codes (2XX, 4XX, etc), see [_Vitals Metrics_](/gateway/{{page.release}}/vitals/vitals-metrics/). + +5. To download your report, click **Export**. A CSV file containing your Vitals report data downloads to your system. + +## Export Vitals Data to a CSV Report + +1. Create a Vitals report, as defined above in [Generate a Vitals Report](#generate-a-vitals-report). + +2. Click **Export** to download a CSV file to your system. diff --git a/app/gateway/2.6.x/vitals/vitalsSpec.yaml b/app/gateway/2.6.x/vitals/vitalsSpec.yaml new file mode 100644 index 000000000000..2cbcf24c9dfb --- /dev/null +++ b/app/gateway/2.6.x/vitals/vitalsSpec.yaml @@ -0,0 +1,847 @@ +swagger: '2.0' +info: + description: Vitals API + version: 2.4.0 + title: Vitals API +basePath: / +tags: + - name: health + description: Stats about the health of a Kong cluster + - name: traffic + description: Stats about traffic routed through Kong +schemes: + - http +paths: + /vitals: + get: + tags: + - vitals + summary: Get information about stats collected + description: '' + operationId: getVitalsInfo + produces: + - application/json + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/VitalsInfo' + /vitals/cluster: + get: + tags: + - health + summary: Get health stats for this Kong cluster + description: '' + operationId: getClusterStats + produces: + - application/json + parameters: + - name: interval + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ClusterVitalsTimeSeriesWithMetadata' + '400': + description: Invalid query params + /vitals/cluster/status_codes: + get: + deprecated: true + tags: + - traffic + summary: Get the status code classes returned across the cluster + description: This operation is deprecated. Use /status_code_classes. + operationId: getClusterStatusCodeStats + produces: + - application/json + parameters: + - name: interval + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ClusterVitalsStatusCodesWithMetadata' + '400': + description: Invalid query params + /vitals/nodes: + get: + tags: + - health + summary: Get health stats for all nodes + description: '' + operationId: getAllNodeStats + produces: + - application/json + parameters: + - name: interval + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/NodeVitalsTimeSeriesWithMetadata' + '400': + description: Invalid query params + '/vitals/nodes/{node_id}': + get: + tags: + - health + summary: Get stats for a specific node by UUID + description: '' + operationId: getNodeStatsByID + produces: + - application/json + parameters: + - name: node_id + type: string + in: path + description: Node to retrieve stats for + required: true + - name: interval + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/NodeVitalsTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested node + '/{workspace_name}/vitals/consumers/{consumer_id}/cluster': + get: + tags: + - traffic + deprecated: true + summary: Get count of requests for the given consumer across entire cluster + description: This operation is deprecated. Use /vitals/status_codes/by_consumer_and_route + operationId: getConsumerClusterStats + produces: + - application/json + parameters: + - name: workspace_name + type: string + in: path + description: Workspace containing the requested consumer. + required: true + - name: consumer_id + type: string + in: path + description: Consumer to retrieve stats for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ClusterConsumersTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested consumer + /{workspace_name}/vitals/status_code_classes: + get: + tags: + - traffic + summary: Get status code classes for a cluster or workspace. + description: '' + operationId: getStatusCodeClassesByWorkspace + produces: + - application/json + parameters: + - name: workspace_name + type: string + in: path + description: >- + Optional parameter. If provided, returns status code classes for the + workspace; otherwise, returns them for the cluster + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested consumer + /{workspace_name}/vitals/status_codes/by_service: + get: + tags: + - traffic + summary: Get a time series of status codes returned by a given service + description: '' + operationId: getStatusCodesByService + produces: + - application/json + parameters: + - name: service_id + type: string + in: query + description: Service to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: workspace_name + type: string + in: path + description: Workspace containing the requested service. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested service + /{workspace_name}/vitals/status_codes/by_route: + get: + tags: + - traffic + summary: Get cluster-wide count of status for a given route + description: '' + operationId: getStatusCodesByRoute + produces: + - application/json + parameters: + - name: route_id + type: string + in: query + description: Route to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: workspace_name + type: string + in: path + description: Workspace containing the requested route. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested route + /{workspace_name}/vitals/status_codes/by_consumer: + get: + tags: + - traffic + summary: Get cluster-wide count of status for a given consumer + description: '' + operationId: getStatusCodesByRoute + produces: + - application/json + parameters: + - name: consumer_id + type: string + in: query + description: Route to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: workspace_name + type: string + in: path + description: Workspace containing the requested consumer. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested route + '/{workspace_name}/vitals/status_codes/by_consumer_and_route': + get: + tags: + - traffic + summary: >- + Get status codes for all the routes called by the given consumer in the + given timeframe + description: '' + operationId: getStatusCodesByConsumerAndRoute + produces: + - application/json + parameters: + - name: consumer_id + type: string + in: query + description: Consumer to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: workspace_name + type: string + in: path + description: Workspace containing the requested consumer and route. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested consumer +definitions: + ClusterVitalsMetadata: + properties: + level: + type: string + example: cluster + enum: + - cluster + - node + workspace_id: + type: string + description: UUID of workspace this time series is for + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - cache_datastore_hits_total + - cache_datastore_misses_total + - latency_proxy_request_min_ms + - latency_proxy_request_max_ms + - latency_upstream_min_ms + - latency_upstream_max_ms + - requests_proxy_total + - latency_proxy_request_avg_ms + - latency_upstream_avg_ms + StatusCodesByEntityMetadata: + properties: + entity_type: + type: string + example: service|route + entity_id: + type: string + example: + level: + type: string + example: cluster + enum: + - cluster + workspace_id: + type: string + description: UUID of the workspace this time series is for + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - status_codes_service|route_total + StatusCodesByEntityTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/StatusCodesByEntityMetadata' + stats: + $ref: '#/definitions/StatusCodesByEntityStats' + ClusterVitalsStatusCodesMetadata: + properties: + level: + type: string + example: cluster + enum: + - cluster + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - status_code_classes_total + ClusterVitalsStats: + properties: + cluster: + type: object + properties: + : + type: array + items: + type: integer + description: >- + List of stat values collected at "timestamp_n", in same order as + "meta.stat_labels" + example: + - 999 + - 130 + - 0 + - 35 + - 142 + - 528 + - 1146 + - 110 + - 156 + StatusCodesByEntityStats: + properties: + cluster: + type: object + description: Vitals status codes data available at the cluster level + properties: + : + type: object + properties: + : + type: integer + description: >- + The total count of a particular status code for the time + period + example: 1824 + ClusterVitalsStatusCodesStats: + properties: + cluster: + type: object + description: Vitals status codes data available at the cluster level + properties: + : + type: object + properties: + : + type: integer + description: >- + The total count of a particular status code class for the time + period + example: 1824 + ClusterVitalsTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/ClusterVitalsMetadata' + stats: + $ref: '#/definitions/ClusterVitalsStats' + ClusterVitalsStatusCodesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/ClusterVitalsStatusCodesMetadata' + stats: + $ref: '#/definitions/ClusterVitalsStatusCodesStats' + ClusterConsumersMetadata: + properties: + level: + type: string + example: cluster + enum: + - cluster + - node + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - requests_consumer_total + ClusterConsumersStats: + properties: + cluster: + type: object + properties: + : + type: integer + description: >- + List of stat values collected at "timestamp_n", in same order as + "meta.stat_labels" + example: 47 + ClusterConsumersTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/ClusterConsumersMetadata' + stats: + $ref: '#/definitions/ClusterConsumersStats' + NodeVitalsMetadata: + properties: + level: + type: string + example: node + enum: + - cluster + - node + workspace_id: + type: string + description: UUID of the workspace this time series is for + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - cache_datastore_hits_total + - cache_datastore_misses_total + - latency_proxy_request_min_ms + - latency_proxy_request_max_ms + - latency_upstream_min_ms + - latency_upstream_max_ms + - requests_proxy_total + - latency_proxy_request_avg_ms + - latency_upstream_avg_ms + nodes: + type: object + description: >- + table of node ids that contributed to this time series. This element + is not included on cluster-level requests. + properties: + : + type: object + description: The id of a node included in this time series. + properties: + hostname: + type: string + description: The name of the host where this node runs + NodeVitalsStats: + properties: + : + type: object + description: >- + The node this time series is for, or "cluster" if it's a cluster-level + time series. + properties: + : + type: array + items: + type: integer + description: >- + List of stat values collected at "timestamp_n", in same order as + "meta.stat_labels" + example: + - 999 + - 130 + - 0 + - 35 + - 142 + - 528 + - 1146 + - 110 + - 156 + NodeVitalsTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/NodeVitalsMetadata' + stats: + $ref: '#/definitions/NodeVitalsStats' + VitalsInfo: + type: object + example: + stats: + cache_datastore_hits_total: + levels: + cluster: + intervals: + days: + retention_period_seconds: 63072000 + minutes: + retention_period_seconds: 90000 + seconds: + retention_period_seconds: 3600 + nodes: + intervals: + days: + retention_period_seconds: 63072000 + minutes: + retention_period_seconds: 90000 + seconds: + retention_period_seconds: 3600 + properties: + stats: + type: object + properties: + : + type: object + properties: + levels: + type: object + description: >- + Vitals data is tracked and aggregated at different levels (per + cluster, per node) + properties: + cluster: + type: object + description: Vitals data available at the cluster level + properties: + intervals: + type: object + description: >- + Vitals data is available at different intervals + (seconds, minutes, days) + properties: + days: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the days interval + minutes: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the minutes interval + seconds: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the seconds interval + nodes: + type: object + description: Vitals data available at the node level + properties: + intervals: + type: object + description: >- + Vitals data is available at different intervals + (seconds, minutes, days) + properties: + days: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the days interval + minutes: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the minutes interval + seconds: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the seconds interval diff --git a/app/gateway/2.7.x/admin-api/admins/examples.md b/app/gateway/2.7.x/admin-api/admins/examples.md new file mode 100644 index 000000000000..2baf297fe948 --- /dev/null +++ b/app/gateway/2.7.x/admin-api/admins/examples.md @@ -0,0 +1,57 @@ +--- +title: Admins Examples +badge: enterprise +--- + +## How to Invite and Register an Admin + +### Introduction + +Can be used for automation + +### Prerequisites + +```bash +export USERNAME= +export EMAIL= +export WORKSPACE= +export HOST= +export TOKEN=Kong-Admin-Token: +``` + +for example: +```bash +export USERNAME=drogon +export EMAIL=test@test.com +export WORKSPACE=default +export HOST=127.0.0.1:8001 +export ADMIN_TOKEN=Kong-Admin-Token:hunter2 +``` + +May benefit from HTTPie and jq. + +## Step 1 +Extract and store the token from the registration URL, either by manually creating an environment variable or by echoing and piping with `jq`: + +#### Manual method example: + +1. Send a request to the registration URL +```bash +http $HOST/$WORKSPACE/admins/$USERNAME?generate_register_url=true $TOKEN +``` + +2. Copy the response and export as an environment variable, for example: +```bash +export REGISTER_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDUwNjc0NjUsImlkIjoiM2IyNzY3MzEtNjIxZC00ZjA3LTk3YTQtZjU1NTg0NmJkZjJjIn0.gujRDi2pX_E7u2zuhYBWD4MoPFKe3axMAq-AUcORg2g +``` + +#### Programmatic method (requires `jq`): +```bash +REGISTER_TOKEN=$(http $HOST/$WORKSPACE/admins/$USERNAME?generate_register_url=true $TOKEN | jq .token -r) +``` + +## Step 2 + +```bash +http $HOST/$WORKSPACE/admins/register token=$REGISTER_TOKEN username=$USERNAME email=$EMAIL password="" +``` diff --git a/app/gateway/2.7.x/admin-api/admins/reference.md b/app/gateway/2.7.x/admin-api/admins/reference.md new file mode 100644 index 000000000000..8a9956f71cad --- /dev/null +++ b/app/gateway/2.7.x/admin-api/admins/reference.md @@ -0,0 +1,327 @@ +--- +title: Admins Reference +badge: enterprise +--- + +## List Admins +**Endpoint** + +
    /admins
    + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [{ + "created_at": 1556638385, + "id": "665b4070-541f-48bf-82c1-53030babaa81", + "updated_at": 1556638385, + "status": 4, + "username": "test-admin", + "email": "test@test.com", + "rbac_token_enabled": true + }, { + "created_at": 1556563122, + "id": "a93ff120-9e6c-4198-b47e-f779104c7eac", + "updated_at": 1556563122, + "status": 0, + "username": "kong_admin", + "rbac_token_enabled": false + }], + "next": null +} +``` + +## Invite an Admin +**Endpoint** + +
    /admins
    + +| Attribute | Description | +|-------------|------------------------------------------------------------| +| `email` | The **Admin**'s email address | +| `username` | The **Admin**'s username | +| `custom_id`
    optional | The **Admin**'s custom ID | +| `rbac_token_enabled` | Allows the **Admin** to use and reset their RBAC token; `true` by default | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "admin": { + "created_at": 1556638641, + "id": "8f0a742f-07f3-49e0-90d7-4fc7eea7e6a4", + "updated_at": 1556638641, + "status": 4, + "username": "test-case-3", + "email": "test3@test.com", + "rbac_token_enabled": true + } +} +``` + +## Register an Admin's Credentials +**Endpoint** + +
    /admins/register
    + +| Attribute | Description | +|-------------|---------------------------| +| `token` | The authentication token | +| `username` | The **Admin**'s username | +| `email` | The **Admin**'s email address | +| `password` | The **Admin**'s new password | + +**Response** + +``` +HTTP 201 Created +``` + +## Send a Password-Reset Email to an Admin +**Endpoint** + +
    /admins/password_resets
    + +| Attribute | Description | +|-------------|------------------------------------------------------------| +| `email` | The **Admin**'s email address | + +**Response** + +``` +HTTP 201 Created +``` + +## Reset an Admin's Password +**Endpoint** + +
    /admins/password_resets
    + +| Attribute | Description | +|-------------|------------------------------------------------------------| +| `email` | The **Admin**'s email address | +| `password` | The **Admin**'s new password | +| `token` | The authentication token | + +**Response** + +``` +HTTP 200 OK +``` + +## Retrieve an Admin +**Endpoint** + +
    /admins/{name_or_id}
    + +| Attribute | Description | +|------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | +| `generate_register_url`
    optional | `true` returns a unique registration URL for the **Admin** | + +**Notes:** +* `generate_register_url` will only generate a URL if the **Admin**'s +invitation status is 4 ("invited"). +* `generate_register_url` will override the previous registration URL +for the particular **Admin** each time it is requested. + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1556638385, + "id": "665b4070-541f-48bf-82c1-53030babaa81", + "updated_at": 1556638385, + "status": 4, + "username": "test-admin", + "email": "test@test.com", + "rbac_token_enabled": true +} +``` + +## Update an Admin +**Endpoint** + +
    /admins/{name_or_id}
    + +| Attribute | Description | +|----------------------|--------------------------------------------| +| `name_or_id` | The **Admin**'s current username or custom ID | +| `email`
    optional | The **Admin**'s new email address | +| `username`
    optional | The **Admin**'s new username | +| `custom_id`
    optional | The **Admin**'s new custom ID | +| `rbac_token_enabled` | Allows the **Admin** to use and reset their RBAC token; `true` by default | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1556638385, + "id": "665b4070-541f-48bf-82c1-53030babaa81", + "updated_at": 1556639017, + "status": 4, + "username": "test-renamed", + "email": "test@test.com" + "rbac_token_enabled": true +} +``` + +## Delete an Admin +**Endpoint** + +
    /admins/{name_or_id}
    + +| Attribute | Description | +|--------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | + +**Response** + +``` +HTTP 204 No Content +``` + +## List an Admin's Roles +**Endpoint** + +
    /admins/{name_or_id}/roles
    + +| Attribute | Description | +|--------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "roles": [{ + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1556563122, + "id": "7574eb1d-c9fa-46a9-bd3a-3f1b4b196287", + "name": "read-only", + "is_default": false + }, { + "comment": "Full access to all endpoints, across all workspaces—except RBAC Admin API", + "created_at": 1556563122, + "id": "7fdea5c8-2bfa-4aa9-9c21-7bb9e607186d", + "name": "admin", + "is_default": false + }] +} +``` + +## Create or Update an Admin's Roles +**Endpoint** + +
    /admins/{name_or_id}/roles
    + +| Attribute | Description | +|--------------|-----------------------------------------------------------| +| `name_or_id` | The **Admin**'s current username or ID | +| `roles` | (comma separated) string of names of Roles to create or update for an **Admin** | + +**Response** + +``` +HTTP 201 OK +``` + + +```json +{ + "roles": [{ + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1556563122, + "id": "7574eb1d-c9fa-46a9-bd3a-3f1b4b196287", + "name": "read-only", + "is_default": false + }, { + "comment": "Full access to all endpoints, across all workspaces—except RBAC Admin API", + "created_at": 1556563122, + "id": "7fdea5c8-2bfa-4aa9-9c21-7bb9e607186d", + "name": "admin", + "is_default": false + }, { + "comment": "Full access to all endpoints, across all workspaces", + "created_at": 1556563122, + "id": "99bd8d18-f5b6-410e-aefe-d75f4252f13c", + "name": "super-admin", + "is_default": false + }] +} +``` + +## Delete an Admin's Role +**Endpoint** + +
    /admins/{name_or_id}/roles
    + +| Attribute | Description | +|--------------|-----------------------------------------------------------| +| `name_or_id` | The **Admin**'s current username or custom ID | +| `roles` | (comma separated) string of names of Roles to remove from an **Admin** | + +**Response** + +``` +HTTP 204 No Content +``` + +## List an Admin's Workspaces +**Endpoint** + +
    /admins/{name_or_id}/workspaces
    + +| Attribute | Description | +|--------------|-----------------------------------| +| `name_or_id` | The **Admin**'s username or ID | + +**Response** + +``` +HTTP 200 OK +``` + +```json +[{ + "created_at": 1556563122, + "config": { + "portal": true, + "portal_auto_approve": true + }, + "id": "00000000-0000-0000-0000-000000000000", + "name": "default", + "meta": {} +}, { + "created_at": 1556570807, + "config": { + "portal": true + }, + "id": "57b3ce24-6d29-427f-af13-15bd60430e56", + "name": "sdfgsdfg", + "meta": { + "color": "#3894f0" + } +}] +``` diff --git a/app/gateway/2.7.x/admin-api/audit-log.md b/app/gateway/2.7.x/admin-api/audit-log.md new file mode 100644 index 000000000000..d66d0c87e617 --- /dev/null +++ b/app/gateway/2.7.x/admin-api/audit-log.md @@ -0,0 +1,496 @@ +--- +title: Admin API Audit Log +badge: enterprise +--- + +{{site.base_gateway}} provides a granular logging facility on its Admin API. This +allows cluster administrators to keep detailed track of changes made to the +cluster configuration throughout its lifetime, aiding in compliance efforts and +providing valuable data points during forensic investigations. Generated audit +log trails are [Workspace](/gateway/{{page.release}}/admin-api/workspaces/reference/) and [RBAC](/gateway/{{page.release}}/admin-api/rbac/reference/)-aware, +providing Kong operators a deep and wide look into changes happening within +the cluster. + +## Getting Started + +Audit logging is disabled by default. It is configured via the Kong configuration (e.g. `kong.conf`): + +```bash +audit_log = on # audit logging is enabled +audit_log = off # audit logging is disabled +``` + +or via environment variables: + +```bash +export KONG_AUDIT_LOG=on +export KONG_AUDIT_LOG=off +``` + +As with other Kong configurations, changes take effect on `kong reload` or `kong +restart`. + +## Request Audits + +### Generating and Viewing Audit Logs + +Audit logging provides granular details of each HTTP request that was handled by +Kong's Admin API. Audit log data is written to Kong's back database. As a result, +request audit logs are available via the Admin API (in addition to via direct +database query). For example, consider a query to the Admin API to the `/status` +endpoint: + +``` +vagrant@ubuntu-xenial:/kong$ http :8001/status +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:32:47 GMT +Server: kong/0.34-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: ZuUfPfnxNn7D2OTU6Xi4zCnQkavzMUNM + +{ + "database": { + "reachable": true + }, + "server": { + "connections_accepted": 1, + "connections_active": 1, + "connections_handled": 1, + "connections_reading": 0, + "connections_waiting": 0, + "connections_writing": 1, + "total_requests": 1 + } +} +``` + +The above interaction with the Admin API generates a correlating entry in +the audit log table. Querying the audit log via Admin API returns the details of the interaction above: + +``` +http :8001/audit/requests +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:35:24 GMT +Server: kong/0.34-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: VXgMG1Y3rZKbjrzVYlSdLNPw8asVwhET + +{ + "data": [ + { + "client_ip": "127.0.0.1", + "method": "GET", + "path": "/status", + "payload": null, + "request_id": "ZuUfPfnxNn7D2OTU6Xi4zCnQkavzMUNM", + "request_timestamp": 1581617463, + "signature": null, + "status": 200, + "ttl": 2591995, + "workspace": "0da4afe7-44ad-4e81-a953-5d2923ce68ae" + } + ], + "total": 1 +} +``` + +Note the value of the `request_id` field. This is tied to the +`X-Kong-Admin-Request-ID` response header received in the first transaction. +This allows close association of client requests and audit log records within +the Kong cluster. + +Because every audit log entry is made available via Kong's Admin API, it is +possible to transport audit log entries into existing logging warehouses, SIEM +solutions, or other remote services for duplication and inspection. + +### Workspaces and RBAC + +Audit log entries are written with an awareness of the requested Workspace, and +the RBAC user (if present). When RBAC is enforced, the RBAC user's UUID will be +written to the `rbac_user_id` field in the audit log entry: + +``` +{ + "data": [ + { + "client_ip": "127.0.0.1", + "method": "GET", + "path": "/status", + "payload": null, + "rbac_user_id": "2e959b45-0053-41cc-9c2c-5458d0964331", + "request_id": "QUtUa3RMbRLxomqcL68ilOjjl68h56xr", + "request_timestamp": 1581617463, + "signature": null, + "status": 200, + "ttl": 2591995, + "workspace": "0da4afe7-44ad-4e81-a953-5d2923ce68ae" + } + ], + "total": 1 +} +``` + +Note also the presence of the `workspace` field. This is the UUID of the Workspace with which the request was associated. + +### Limiting Audit Log Generation + +It may be desirable to ignore audit log generation for certain Admin API +requests such as innocuous requests to the `/status` endpoint for +health checking or to ignore requests for a given path prefix (e.g. a given +Workspace). To this end, the `audit_log_ignore_methods` and +`audit_log_ignore_paths` configuration options are presented: + +```bash +audit_log_ignore_methods = GET,OPTIONS +# do not generate an audit log entry for GET or OPTIONS HTTP requests +audit_log_ignore_paths = /foo,/status,^/services,/routes$,/one/.+/two,/upstreams/ +# do not generate an audit log entry for requests that match the above regular expressions +``` + +The values of `audit_log_ignore_paths` are matched via a Perl-compatible regular expression. + +For example, when `audit_log_ignore_paths = /foo,/status,^/services,/routes$,/one/.+/two,/upstreams/`, the following request paths do not generate an audit-log entry in the database: + +- `/status` +- `/status/` +- `/foo` +- `/foo/` +- `/services` +- `/services/example/` +- `/one/services/two` +- `/one/test/two` +- `/routes` +- `/plugins/routes` +- `/one/routes/two` +- `/upstreams/` +- `bad400request` + +The following request paths generate an audit log entry in the database: + +- `/example/services` +- `/routes/plugins` +- `/one/two` +- `/routes/` +- `/upstreams` + +### Audit Log Retention + +Request audit records are kept in the database for a duration defined by the +`audit_log_record_ttl` [Kong configuration property](/gateway/{{page.release}}/reference/configuration/#audit_log_record_ttl). +Records in the database older than `audit_log_record_ttl` seconds are automatically +purged. In Cassandra databases, record deletion is handled automatically via the +Cassandra TTL mechanism. In PostgreSQL databases, records are purged via the stored +procedure that is executed on insert into the record database. Thus, request +audit records may exist in the database longer than the configured TTL, if no new +records are inserted to the audit table following the expiration timestamp. + +## Database Audits + +### Generating and Viewing Audit Logs + +In addition to Admin API request data, Kong will generate granular audit log +entries for all insertions, updates, and deletions to the cluster database. +Database update audit logs are also associated with Admin API request unique +IDs. Consider the following request to create a Consumer: + +``` +http :8001/consumers username=bob +HTTP/1.1 201 Created +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:50:18 GMT +Server: kong/0.34-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: 59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2 + +{ + "created_at": 1542131418000, + "id": "16787ed7-d805-434a-9cec-5e5a3e5c9e4f", + "type": 0, + "username": "bob" +} + +``` + +As seen before, a request audit log is generated with details about the request. +Note the presence of the `payload` field, recorded when the request body is +present: + +``` +http :8001/audit/requests +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:52:41 GMT +Server: kong/0.34-dev-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: SpPaxLTkDNndzKaYiWuZl3xrxDUIiGRR + +{ + "data": [ + { + "client_ip": "127.0.0.1", + "method": "POST", + "path": "/consumers", + "payload": "{\"username\": \"bob\"}", + "request_id": "59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2", + "request_timestamp": 1581617463, + "signature": null, + "status": 201, + "ttl": 2591995, + "workspace": "fd51ce6e-59c0-4b6b-b991-aa708a9ff4d2" + } + ], + "total": 1 +} +``` + +Additionally, audit logs are generated to track the creation of the +database entity: + +``` +http :8001/audit/objects +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Type: application/json; charset=utf-8 +Date: Tue, 13 Nov 2018 17:53:27 GMT +Server: kong/0.34-dev-enterprise-edition +Transfer-Encoding: chunked +X-Kong-Admin-Request-ID: ZKra3QT0d3eJKl96jOUXYueLumo0ck8c + +{ + "data": [ + { + "dao_name": "consumers", + "entity": "{\"created_at\":1542131418000,\"id\":\"16787ed7-d805-434a-9cec-5e5a3e5c9e4f\",\"username\":\"bob\",\"type\":0}", + "entity_key": "16787ed7-d805-434a-9cec-5e5a3e5c9e4f", + "expire": 1544723418009, + "id": "7ebabee7-2b09-445d-bc1f-2092c4ddc4be", + "operation": "create", + "request_id": "59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2", + "request_timestamp": 1581617463, + }, + ], + "total": 1 +} +``` + +Object audit entries contain information about the entity updated, including the +entity body itself, its database primary key, and the type of operation +performed (`create`, `update`, or `delete`). Note also the associated + `request_id` field. + +### Limiting Audit Log Generation + +As with request audit logs, it may be desirable to skip generation of audit logs +for certain database tables. This is configurable via the +`audit_log_ignore_tables` Kong config option: + +``` +audit_log_ignore_tables = consumers +# do not generate database audit logs for changes to the consumers table +``` + +### Audit Log Retention + +Database audit records are kept in the database for a duration defined by the +`audit_log_record_ttl` [Kong configuration property](/gateway/{{page.release}}/reference/configuration/#audit_log_record_ttl). +Records in the database older than `audit_log_record_ttl` seconds are automatically +purged. In Cassandra databases, record deletion is handled automatically via the +Cassandra TTL mechanism. In PostgreSQL databases, records are purged via the stored +procedure that is executed on insert into the record database. Thus, database +audit records may exist in the database longer than the configured TTL, if no new +records are inserted to the audit table following the expiration timestamp. + +## Digital Signatures + +To provide non-repudiation, audit logs may be signed with a private RSA key. When +enabled, a lexically sorted representation of each audit log entry is signed by +the defined private key; the signature is stored in an additional field within +the record itself. The public key should be stored elsewhere and can be used +later to validate the signature of the record. + +### Setting Up Log Signing + +Generate a private key via the `openssl` tool: + +```bash +openssl genrsa -out private.pem 2048 +``` + +Extract the public key for future audit verification: + +``` +openssl rsa -in private.pem -outform PEM -pubout -out public.pem +``` + +Configure Kong to sign audit log records: + +``` +audit_log_signing_key = /path/to/private.pem +``` + +Audit log entries will now contain a field `signature`: + +``` +{ + "client_ip": "127.0.0.1", + "method": "GET", + "path": "/status", + "payload": null, + "request_id": "Ka2GeB13RkRIbMwBHw0xqe2EEfY0uZG0", + "request_timestamp": 1581617463, + "signature": "l2LWYaRIHfXglFa5ehFc2j9ijfERazxisKVtJnYa+QUz2ckcytxfOLuA4VKEWHgY7cCLdn5C7uRJzE6es5V2SoOV59NOpskkr5lTt9kzao64UEw5UNOdeZYZKwyhG9Ge7IsxTK6haW0iG3a9dHqlKlwvnHZTbFM8TUV/umg8sJ1QJ/5ivXecbyHYtD5luKAI6oEgIdZPtQexRkwxlzvfR8lzeC/dDc2slSrjWRbBxNFlgfRKhDdVzVzgu8pEucgKggu67PKLkJ+bQEkxX1+Yg3czIpJyC3t6cgoggb0UNtBq1uUpswe0wdueKh6G5Gzz6XrmOjlv7zSz4gtVyEHZgg==", + "status": 200, + "ttl": 2591995, + "workspace": "fd51ce6e-59c0-4b6b-b991-aa708a9ff4d2" +} +``` + +### Validating Signatures + +To verify record signatures, use the `openssl` utility, or other cryptographic +tools that are capable of validating RSA digital signatures. + +Signatures are generated using a 256-bit SHA digest. The following example +demonstrates how to verify the audit log record shown above. First, store the +record signature on disk after stripping the Base64 +encoding: + +```bash +cat < record_signature +> l2LWYaRIHfXglFa5ehFc2j9ijfERazxisKVtJnYa+QUz2ckcytxfOLuA4VKEWHgY7cCLdn5C7uRJzE6es5V2SoOV59NOpskkr5lTt9kzao64UEw5UNOdeZYZKwyhG9Ge7IsxTK6haW0iG3a9dHqlKlwvnHZTbFM8TUV/umg8sJ1QJ/5ivXecbyHYtD5luKAI6oEgIdZPtQexRkwxlzvfR8lzeC/dDc2slSrjWRbBxNFlgfRKhDdVzVzgu8pEucgKggu67PKLkJ+bQEkxX1+Yg3czIpJyC3t6cgoggb0UNtBq1uUpswe0wdueKh6G5Gzz6XrmOjlv7zSz4gtVyEHZgg== +> EOF +``` + +Next, the audit record must be transformed into its canonical format used for +signature generation. This transformation requires serializing the record into +a string format that can be verified. The format is a lexically-sorted, +pipe-delimited string of each audit log record part, _without_ the `signature`, +`ttl`, or `expire` fields. The following is a canonical +implementation written in Lua: + +```lua +local cjson = require "cjson" +local pl_sort = require "pl.tablex".sort + +local function serialize(data) + local p = {} + + data.signature = nil + data.expire = nil + data.ttl = nil + + for k, v in pl_sort(data) do + if type(v) == "table" then + p[#p + 1] = serialize(v) + elseif v ~= cjson.null then + p[#p + 1] = v + end + end + + return p +end + +table.concat(serialize(data), "|") +``` + +For example, the canonical format of the audit record above is: + +``` +cat canonical_record.txt +127.0.0.1|1544724298663|GET|/status|Ka2GeB13RkRIbMwBHw0xqe2EEfY0uZG0|1542132298664|200|fd51ce6e-59c0-4b6b-b991-aa708a9ff4d2 +``` + +{:.important} +> Ensure that the contents of the canonical record file on disk match the expected +canonical record format exactly. The presence of any additional bytes, such as +a trailing newline `\n`, will cause a validation failure in the next step. + +Once these two elements are in place, the signature can be verified: + +```bash +openssl dgst -sha256 -verify public.pem -signature record_signature canonical_record.txt +Verified OK +``` + +--- + +## Reference + +### API Reference + +#### List Request Audit Logs + +##### Endpoint + +
    /audit/requests
    + +##### Response + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "client_ip": "127.0.0.1", + "method": "GET", + "path": "/status", + "payload": null, + "request_id": "ZuUfPfnxNn7D2OTU6Xi4zCnQkavzMUNM", + "request_timestamp": 1581617463, + "signature": null, + "status": 200, + "ttl": 2591995, + "workspace": "0da4afe7-44ad-4e81-a953-5d2923ce68ae" + } + ], + "total": 1 +} +``` + +#### List Database Audit Logs + +##### Endpoint + +
    /audit/objects
    + +##### Response + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "dao_name": "consumers", + "entity": "{\"created_at\":1542131418000,\"id\":\"16787ed7-d805-434a-9cec-5e5a3e5c9e4f\",\"username\":\"bob\",\"type\":0}", + "entity_key": "16787ed7-d805-434a-9cec-5e5a3e5c9e4f", + "expire": 1544723418009, + "id": "7ebabee7-2b09-445d-bc1f-2092c4ddc4be", + "operation": "create", + "request_id": "59fpTWlpUtHJ0qnAWBzQRHRDv7i5DwK2" + }, + ], + "total": 1 +} +``` + +### Configuration Reference + +See the [Data & Admin Audit](/gateway/{{page.release}}/reference/configuration/#data--admin-audit) +section of the Configuration Property Reference. diff --git a/app/gateway/2.7.x/admin-api/consumer-groups/examples.md b/app/gateway/2.7.x/admin-api/consumer-groups/examples.md new file mode 100644 index 000000000000..4a44d06eeffe --- /dev/null +++ b/app/gateway/2.7.x/admin-api/consumer-groups/examples.md @@ -0,0 +1,747 @@ +--- +title: Consumer Groups Examples +badge: enterprise +--- + +With consumer groups, you can define any number of rate limiting tiers and +apply them to subsets of consumers, instead of managing each consumer +individually. + +For example, you could define three consumer groups: +* A "gold tier" with 1000 requests per minute +* A "silver tier" with 10 requests per second +* A "bronze tier" with 6 requests per second + +The `consumer_groups` endpoint works together with the [Rate Limiting Advanced plugin](/hub/kong-inc/rate-limiting-advanced/). + +Consumers that are not in a consumer group default to the Rate Limiting advanced +plugin’s configuration, so you can define tier groups for some users and +have a default behavior for ungrouped consumers. + +To use consumer groups for rate limiting, you need to: +* Create one or more consumer groups +* Create consumers +* Assign consumers to groups +* Configure the Rate Limiting Advanced plugin with the `enforce_consumer_groups` +and `consumer_groups` parameters, setting up the list of consumer groups that +the plugin accepts +* Configure rate limiting for each consumer group, overriding the plugin's +configuration + +For all possible requests, see the +[Consumer Groups reference](/gateway/{{page.release}}/admin-api/consumer-groups/reference). + +{:.note} +> **Note:** Consumer groups are not supported in declarative configuration with +decK. If you have consumer groups in your configuration, decK will ignore them. + +## Set up consumer group + +1. Create a consumer group named `JL`: + +{% capture create_consumer_group %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X POST http://{HOSTNAME}:8001/consumer_groups \ + --data name=JL +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http POST :8001/consumer_groups name=JL +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ create_consumer_group | indent | replace: " ", "" }} + + Response: + + ```json + { + "created_at": 1638915521, + "id": "8a4bba3c-7f82-45f0-8121-ed4d2847c4a4", + "name": "JL" + } + ``` + +1. Create a consumer, `DianaPrince`: + +{% capture create_consumer %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X POST http://{HOSTNAME}:8001/consumers \ + --data username=DianaPrince +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http POST :8001/consumers username=DianaPrince +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ create_consumer | indent | replace: " ", "" }} + + Response: + + ```json + { + "created_at": 1638915577, + "custom_id": null, + "id": "8089a0e6-1d31-4e00-bf51-5b902899b4cb", + "tags": null, + "type": 0, + "username": "DianaPrince", + "username_lower": "dianaprince" + } + ``` + +1. Add `DianaPrince` to the `JL` consumer group: + +{% capture add_consumer %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X POST http://{HOSTNAME}:8001/consumer_groups/JL/consumers \ + --data consumer=DianaPrince +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http POST :8001/consumer_groups/JL/consumers consumer=DianaPrince +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ add_consumer | indent | replace: " ", "" }} + + Response: + + ```json + { + "consumer_group": { + "created_at": 1638915521, + "id": "8a4bba3c-7f82-45f0-8121-ed4d2847c4a4", + "name": "JL" + }, + "consumers": [ + { + "created_at": 1638915577, + "id": "8089a0e6-1d31-4e00-bf51-5b902899b4cb", + "type": 0, + "username": "DianaPrince", + "username_lower": "dianaprince" + } + ] + } + ``` + +## Set up Rate Limiting Advanced config for consumer group + +1. Enable the [Rate Limiting Advanced plugin](/hub/kong-inc/rate-limiting-advanced/), +setting the rate limit to five requests (`config.limit`) for every +30 seconds (`config.window_size`): + +{% capture add_plugin %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X POST http://{HOSTNAME}:8001/plugins/ \ + --data name=rate-limiting-advanced \ + --data config.limit=5 \ + --data config.sync_rate=-1 \ + --data config.window_size=30 \ + --data config.window_type=sliding \ + --data config.retry_after_jitter_max=0 \ + --data config.enforce_consumer_groups=true \ + --data config.consumer_groups=JL +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http -f :8001/plugins/ \ + name=rate-limiting-advanced \ + config.limit=5 \ + config.sync_rate=-1 \ + config.window_size=30 \ + config.window_type=sliding \ + config.retry_after_jitter_max=0 \ + config.enforce_consumer_groups=true \ + config.consumer_groups=JL +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ add_plugin | indent | replace: " ", "" }} + + For consumer groups, the following parameters are required: + * `config.enforce_consumer_groups=true`: enables consumer groups for this plugin. + * `config.consumer_groups=JL`: specifies a list of groups that this plugin allows overrides for. + + {:.note} + > **Note:** In this example, you're configuring the plugin globally, so it + applies to all entities (Services, Routes, and Consumers) in the + {{site.base_gateway}} instance. You can also apply it to a + [specific Service or Route](/hub/kong-inc/rate-limiting-advanced/) + for more granular control. + +1. The plugin you just set up applies to all consumers in the cluster. Change +the rate limiting configuration for the `JL` consumer group only, setting +the limit to ten requests for every ten seconds: + +{% capture override %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X PUT http://{HOSTNAME}:8001/consumer_groups/JL/overrides/plugins/rate-limiting-advanced \ + --data config.limit=10 \ + --data config.window_size=10 \ + --data config.retry_after_jitter_max=1 +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http PUT :8001/consumer_groups/JL/overrides/plugins/rate-limiting-advanced \ + config.limit=10 \ + config.window_size=10 \ + config.retry_after_jitter_max=1 +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ override | indent | replace: " ", "" }} + + Response: + + ```json + { + "config": { + "limit": [ + 10 + ], + "retry_after_jitter_max": 1, + "window_size": [ + 10 + ] + }, + "consumer_group": "JL", + "plugin": "rate-limiting-advanced" + } + ``` + +1. Check that it worked by looking at the `JL` consumer group object: + +{% capture check_group1 %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X GET http://{HOSTNAME}:8001/consumer_groups/JL +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http :8001/consumer_groups/JL +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ check_group1 | indent | replace: " ", "" }} + + Notice the `plugins` object in the response, along with the parameters that you + just set for the Rate Limiting Advanced plugin: + + ```json + { + "consumer_group": { + "created_at": 1638915521, + "id": "8a4bba3c-7f82-45f0-8121-ed4d2847c4a4", + "name": "JL" + }, + "consumers": [ + { + "created_at": 1638915577, + "id": "8089a0e6-1d31-4e00-bf51-5b902899b4cb", + "type": 0, + "username": "DianaPrince", + "username_lower": "dianaprince" + } + ], + "plugins": [ + { + "config": { + "limit": [ + 10 + ], + "retry_after_jitter_max": 1, + "window_size": [ + 10 + ], + "window_type": "sliding" + }, + "consumer_group": { + "id": "8a4bba3c-7f82-45f0-8121-ed4d2847c4a4" + }, + "created_at": 1638916518, + "id": "b7c426a2-6fcc-4bfd-9b7a-b66e8f1ad260", + "name": "rate-limiting-advanced" + } + ] + } + ``` + +## Remove consumer from group - group view + +You can remove a consumer from a group by accessing `/consumers` or +`/consumer_groups`. The following steps use `/consumer_groups`. + +1. Check the `JL` consumer group for the consumer name: + +{{ check_group1 | indent | replace: " ", "" }} + + Response: + + ```json + { + "consumer_group": { + "created_at": 1638915521, + "id": "8a4bba3c-7f82-45f0-8121-ed4d2847c4a4", + "name": "JL" + }, + "consumers": [ + { + "created_at": 1638915577, + "id": "8089a0e6-1d31-4e00-bf51-5b902899b4cb", + "type": 0, + "username": "DianaPrince", + "username_lower": "dianaprince" + } + ] + } + ``` + +1. Using the username or ID of the consumer (`DianaPrince` in this example), +remove the consumer from the group: + +{% capture delete_consumer1 %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X DELETE http://{HOSTNAME}:8001/consumer_groups/JL/consumers/DianaPrince +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http DELETE :8001/consumer_groups/JL/consumers/DianaPrince +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ delete_consumer1 | indent | replace: " ", "" }} + + If successful, you receive the following response: + ``` + HTTP/1.1 204 No Content + ``` + +1. To verify, check the consumer group configuration again: + +{{ check_group1 | indent | replace: " ", "" }} + + Response, with no consumers assigned: + + ```json + { + "consumer_group": { + "created_at": 1638917780, + "id": "be4bcfca-b1df-4fac-83cc-5cf6774bf48e", + "name": "JL" + } + } + ``` + +## Remove consumer from group - consumer view + +You can remove a consumer from a group by accessing `/consumers` or +`/consumer_groups`. The following steps use `/consumers`. + +1. If you know the consumer name and not the consumer group name, +you can look up the group through the consumer: + +{% capture check_group2 %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X GET http://{HOSTNAME}:8001/consumers/DianaPrince/consumer_groups +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http :8001/consumers/DianaPrince/consumer_groups +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ check_group2 | indent | replace: " ", "" }} + + Response: + + ```json + { + "consumer_groups": [ + { + "created_at": 1638915521, + "id": "8a4bba3c-7f82-45f0-8121-ed4d2847c4a4", + "name": "JL" + } + ] + } + ``` + +1. Using the username or ID of the group (`JL` in this example), +remove the consumer from the group: + +{% capture delete_consumer2 %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X DELETE http://{HOSTNAME}:8001/consumers/DianaPrince/consumer_groups/JL +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http DELETE :8001/consumers/DianaPrince/consumer_groups/JL +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ delete_consumer2 | indent | replace: " ", "" }} + + If successful, you receive the following response: + ``` + HTTP/1.1 204 No Content + ``` + +1. To verify, check the consumer object configuration: + +{{ check_group1 | indent | replace: " ", "" }} + + Response, with no consumers assigned: + + ```json + { + "consumer_group": { + "created_at": 1638917780, + "id": "be4bcfca-b1df-4fac-83cc-5cf6774bf48e", + "name": "JL" + } + } + ``` + + +## Delete consumer group + +If you don't need a consumer group anymore, you can delete it. This removes +all consumers from the group, and deletes the group itself. The consumers in +the group are not deleted. + +1. Delete a consumer group using the following request: + +{% capture delete_consumer2 %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X DELETE http://{HOSTNAME}:8001/consumer_groups/JL +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http DELETE :8001/consumer_groups/JL +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ delete_consumer2 | indent | replace: " ", "" }} + + If successful, you receive see the following response: + ``` + HTTP/1.1 204 No Content + ``` + +1. Check the list of consumer groups to verify that the `JL` group is gone: + +{% capture check_all_groups %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X GET http://{HOSTNAME}:8001/consumer_groups +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http :8001/consumer_groups +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ check_all_groups | indent | replace: " ", "" }} + + Response: + ```json + { + "data": [], + "next": null + } + ``` + +1. Check a consumer that was in the group to make sure it still exists: + +{% capture check_consumer %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X GET http://{HOSTNAME}:8001/consumers/DianaPrince +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http :8001/consumers/DianaPrince +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ check_consumer | indent | replace: " ", "" }} + + An `HTTP/1.1 200 OK` response means the consumer exists. + + +## Manage multiple consumers + +You can perform many `/consumer_groups` operations in bulk. + +1. Assuming you deleted the group `JL` in the previous section, create it again, +along with another group named `Speedsters`: + +{% capture create_consumer_group2 %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X POST http://{HOSTNAME}:8001/consumer_groups \ + --data name=JL + +curl -i -X POST http://{HOSTNAME}:8001/consumer_groups \ + --data name=Speedsters +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http POST :8001/consumer_groups name=JL + +http POST :8001/consumer_groups name=Speedsters +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ create_consumer_group2 | indent | replace: " ", "" }} + +1. Create two consumers, `BarryAllen` and `WallyWest`: + +{% capture create_two_consumers %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X POST http://{HOSTNAME}:8001/consumers \ + --data username=BarryAllen + +curl -i -X POST http://{HOSTNAME}:8001/consumers \ + --data username=WallyWest +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http POST :8001/consumers username=BarryAllen + +http POST :8001/consumers username=WallyWest +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ create_two_consumers | indent | replace: " ", "" }} + +1. Add both consumers to the `Speedsters` group: +{% capture add_two_consumers %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X POST http://{HOSTNAME}:8001/consumer_groups/Speedsters/consumers \ + --data consumer=BarryAllen \ + --data consumer=WallyWest +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http POST :8001/consumer_groups/Speedsters/consumers \ + consumer:='["BarryAllen", "WallyWest"]' +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ add_two_consumers | indent | replace: " ", "" }} + + {{site.base_gateway}} validates the provided list of consumers before assigning + them to the consumer group. To pass validation, consumers must exist and must + not be in the group already. + + If any consumer fails validation, no consumers are assigned to the group. + + Response, if everything is successful: + + ```json + { + "consumer_group": { + "created_at": 1639432267, + "id": "a905151a-5767-40e8-804e-50eec4d0235b", + "name": "Speedsters" + }, + "consumers": [ + { + "created_at": 1639432286, + "id": "ea904e1d-1f0d-4d5a-8391-cae60cb21d61", + "type": 0, + "username": "BarryAllen", + "username_lower": "barryallen" + }, + { + "created_at": 1639432288, + "id": "065d8249-6fe6-4d80-a0ae-f159caef7af0", + "type": 0, + "username": "WallyWest", + "username_lower": "wallywest" + } + ] + } + ``` + +1. You can clear all consumers from a group with one request. This may be useful +if you need to cycle the group for a new batch of users. + + For example, delete all consumers from the `Speedsters` group: + +{% capture delete_all_consumers %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X DELETE http://{HOSTNAME}:8001/consumer_groups/Speedsters/consumers +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http DELETE :8001/consumer_groups/Speedsters/consumers +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ delete_all_consumers | indent | replace: " ", "" }} + + Response: + ``` + HTTP/1.1 204 No Content + ``` + +1. You can also add a consumer to multiple groups: + * If all groups are allowed by the Rate Limiting Advanced plugin, + only the first group's settings apply. + * Otherwise, whichever group is specified in the Rate Limiting Advanced + plugin becomes active. + + Add `BarryAllen` to two groups, `JL` and `Speedsters`: + +{% capture add_consumer_many_groups %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X POST http://{HOSTNAME}:8001/consumers/BarryAllen/consumer_groups \ + --data group=JL \ + --data group=Speedsters +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http POST :8001/consumers/BarryAllen/consumer_groups \ + group:='["JL", "Speedsters"]' +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ add_consumer_many_groups | indent | replace: " ", "" }} + + The response should look something like this: + + ```json + { + "consumer": { + "created_at": 1639436091, + "custom_id": null, + "id": "6098d577-6741-4cf8-9c86-e68057b8f970", + "tags": null, + "type": 0, + "username": "BarryAllen", + "username_lower": "barryallen" + }, + "consumer_groups": [ + { + "created_at": 1639432267, + "id": "a905151a-5767-40e8-804e-50eec4d0235b", + "name": "JL" + }, + { + "created_at": 1639436107, + "id": "2fd2bdd6-690c-4e49-8296-31f55015496d", + "name": "Speedsters" + } + ] + } + ``` + +1. Finally, you can also remove a consumer from all groups: + +{% capture add_consumer_many_groups %} +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X DELETE http://{HOSTNAME}:8001/consumers/BarryAllen/consumer_groups +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http DELETE :8001/consumers/BarryAllen/consumer_groups +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ add_consumer_many_groups | indent | replace: " ", "" }} + + Response: + ``` + HTTP/1.1 204 No Content + ``` diff --git a/app/gateway/2.7.x/admin-api/consumer-groups/reference.md b/app/gateway/2.7.x/admin-api/consumer-groups/reference.md new file mode 100644 index 000000000000..03c7fb888dbe --- /dev/null +++ b/app/gateway/2.7.x/admin-api/consumer-groups/reference.md @@ -0,0 +1,406 @@ +--- +title: Consumer Groups Reference +badge: enterprise +--- + +Use consumer groups to manage custom rate limiting configuration for +subsets of consumers. + +The `consumer_groups` endpoint works together with the [Rate Limiting Advanced plugin](/hub/kong-inc/rate-limiting-advanced/). +To use consumer groups for rate limiting, configure the plugin with the +`enforce_consumer_groups` and `consumer_groups` parameters, then use the +`/consumer_groups` endpoint to manage the groups. + +For more information and examples of setting up and managing consumer groups, see the +[Consumer Groups examples](/gateway/{{page.release}}/admin-api/consumer-groups/examples). + +{:.note} +> **Note:** Consumer groups are not supported in declarative configuration with +decK. If you have consumer groups in your configuration, decK will ignore them. + +## List consumer groups + +### List all consumer groups + +**Endpoint** + +
    /consumer_groups
    + +**Response** + +``` +HTTP/1.1 200 OK +``` + +```json +{ + "data": [ + { + "created_at": 1557522650, + "id": "42b022c1-eb3c-4512-badc-1aee8c0f50b5", + "name": "my_group" + }, + { + "created_at": 1637706162, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "my_group2" + } + ], + "next": null +} +``` + +### List a specific consumer group + +**Endpoint** + +
    /consumer_groups/{GROUP_NAME|GROUP_ID}
    + +Attribute | Description +---------: | -------- +`GROUP_NAME|GROUP_ID`
    *required* | The name or UUID of the consumer group. + +**Response** + +``` +HTTP/1.1 200 OK +``` + +```json +{ + "consumer_group": { + "created_at": 1638917780, + "id": "be4bcfca-b1df-4fac-83cc-5cf6774bf48e", + "name": "JL" + } +} +``` + + +### List all consumers in a consumer group + +**Endpoint** + +
    /consumer_groups/{GROUP_NAME|GROUP_ID}/consumers
    + +Attribute | Description +---------: | -------- +`GROUP_NAME|GROUP_ID`
    *required* | The name or UUID of the consumer group. + +**Response** + +``` +HTTP/1.1 200 OK +``` + +```json +{ + "consumers": [ + { + "created_at": 1638918560, + "id": "288f2bfc-04e2-4ec3-b6f3-40408dff5417", + "type": 0, + "username": "BarryAllen", + "username_lower": "barryallen" + }, + { + "created_at": 1638915577, + "id": "8089a0e6-1d31-4e00-bf51-5b902899b4cb", + "type": 0, + "username": "DianaPrince", + "username_lower": "dianaprince" + } + ] +} +``` + +### List consumer groups for a consumer + +View all consumer groups that a consumer is assigned to. + +**Endpoint** + +
    /consumers/{CONSUMER_NAME|CONSUMER_ID}/consumer_groups
    + +Attribute | Description +---------: | -------- +`USERNAME|CONSUMER_ID`
    *required* | The name or UUID of the consumer. + +**Response** + +``` +HTTP/1.1 200 OK +``` + +```json +{ + "consumer_groups": [ + { + "created_at": 1638918476, + "id": "e2c3f16e-22c7-4ef4-b6e4-ab25c522b339", + "name": "JL" + } + ] +} +``` + + +## Create a consumer group + +**Endpoint** + +
    /consumer_groups
    + +**Request body** + +Attribute | Description +---------: | -------- +`name`
    *required* | A unique name for the consumer group you want to create. + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "created_at": 1557522650, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "JL", +} +``` + +**Endpoint** + +
    /consumer_groups/{GROUP_NAME}
    + +Attribute | Description +---------: | -------- +`GROUP_NAME`
    *required* | A unique name for the consumer group you want to create. + + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "created_at": 1557522650, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "JL", +} +``` + +## Add a consumer to a group + +Add a consumer to a specific consumer group. + +If you add a consumer to multiple groups: +* If all groups are allowed by the Rate Limiting Advanced plugin, +only the first group's settings will apply. +* Otherwise, whichever group is specified in the Rate Limiting Advanced +plugin will be active. + +**Consumers endpoint** +
    /consumers/{CONSUMER_NAME|CONSUMER_ID}/consumer_groups
    + +Attribute | Description +---------: | -------- +`CONSUMER_NAME|CONSUMER_ID`
    *required* | The name or UUID of the consumer. + +**Request body** + +Attribute | Description +---------: | -------- +`group`
    *required* | The name or ID of the group to add the consumer to. + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "consumer": { + "created_at": 1638918560, + "custom_id": null, + "id": "288f2bfc-04e2-4ec3-b6f3-40408dff5417", + "tags": null, + "type": 0, + "username": "BarryAllen", + "username_lower": "barryallen" + }, + "consumer_groups": [ + { + "created_at": 1638918476, + "id": "e2c3f16e-22c7-4ef4-b6e4-ab25c522b339", + "name": "JL" + } + ] +} +``` + +**Consumer groups endpoint** +
    /consumer_groups/{GROUP_NAME|GROUP_ID}/consumers
    + +Attribute | Description +---------: | -------- +`GROUP_NAME|GROUP_ID`
    *required* | The name or UUID of the consumer group. + + +**Request body** + +Attribute | Description +---------: | -------- +`consumer`
    *required* | The name or ID of the consumer to add to this group. + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "consumer_group": { + "created_at": 1638915521, + "id": "8a4bba3c-7f82-45f0-8121-ed4d2847c4a4", + "name": "JL" + }, + "consumers": [ + { + "created_at": 1638915577, + "id": "8089a0e6-1d31-4e00-bf51-5b902899b4cb", + "type": 0, + "username": "DianaPrince", + "username_lower": "dianaprince" + } + ] +} +``` + +## Delete a consumer group + +Deleting a consumer group removes all consumers from that group. It does +**not** delete any consumers. + +**Endpoint** +
    /consumer_groups/{GROUP_NAME|GROUP_ID}
    + +Attribute | Description +---------: | -------- +`GROUP_NAME|GROUP_ID`
    *required* | The name or UUID of the consumer group to delete. + +**Response** + +``` +HTTP/1.1 204 No Content +``` + +## Remove consumers + +### Remove a consumer from all groups + +**Endpoint** +
    /consumers/{CONSUMER_NAME|CONSUMER_ID}/consumer_groups
    + +Attribute | Description +---------: | -------- +`CONSUMER_NAME|CONSUMER_ID`
    *required* | The name or UUID of the consumer to remove from all groups. + +**Response** + +``` +HTTP/1.1 204 No Content +``` + +### Remove a consumer from a consumer group + +**Consumer endpoint** +
    /consumers/{CONSUMER_NAME|CONSUMER_ID}/consumer_groups/{GROUP_NAME|GROUP_ID}
    + +Attribute | Description +---------: | -------- +`CONSUMER_NAME|CONSUMER_ID`
    *required* | The name or UUID of the consumer to remove. +`GROUP_NAME|GROUP_ID`
    *required* | The name or UUID of the consumer group to remove the consumer from. + +**Response** + +``` +HTTP/1.1 204 No Content +``` + +**Consumer groups endpoint** +
    /consumer_groups/{GROUP_NAME|GROUP_ID}/consumers/{CONSUMER_NAME|CONSUMER_ID}
    + +Attribute | Description +---------: | -------- +`GROUP_NAME|GROUP_ID`
    *required* | The name or UUID of the consumer group to remove the consumer from. +`CONSUMER_NAME|CONSUMER_ID`
    *required* | The name or UUID of the consumer to remove. + +**Response** + +``` +HTTP/1.1 204 No Content +``` + +### Remove all consumers from a consumer group + +
    /consumer_groups/{GROUP_NAME|GROUP_ID}/consumers
    + +Attribute | Description +---------: | -------- +`GROUP_NAME|GROUP_ID`
    *required* | The name or UUID of the consumer group to remove all consumers from. + +**Response** + +``` +HTTP/1.1 204 No Content +``` + +## Configure rate limiting for a consumer group + +Define custom rate limiting settings for a consumer group. This endpoint +overrides the settings of the Rate Limiting Advanced plugin. + +
    /consumer_groups/{GROUP_NAME|GROUP_ID}/overrides/plugins/rate-limiting-advanced
    + +Attribute | Description +---------: | -------- +`GROUP_NAME|GROUP_ID`
    *required* | The name or UUID of the consumer group to configure. + +**Request Body** + +Attribute | Description +---------: | -------- +`config.limit`
    *required* | An array of one or more requests-per-window limits to apply. There must be a matching number of window limits and sizes specified. +`config.window_size`
    *required* | An array of one or more window sizes to apply a limit to (defined in seconds). There must be a matching number of window limits and sizes specified. +`config.window_type`
    *optional* | Set the time window type to either `sliding` (default) or `fixed`. +`config.retry_after_jitter_max`
    *optional* | The upper bound of a jitter (random delay) in seconds to be added to the `Retry-After` header of denied requests (status = `429`) in order to prevent all the clients from coming back at the same time. The lower bound of the jitter is `0`; in this case, the `Retry-After` header is equal to the `RateLimit-Reset` header. + +**Response** + +``` +HTTP/1.1 201 Created +``` + +```json +{ + "config": { + "limit": [ + 10 + ], + "retry_after_jitter_max": 0, + "window_size": [ + 10 + ], + "window_type": "sliding" + }, + "group": "test-group", + "plugin": "rate-limiting-advanced" +} +``` diff --git a/app/gateway/2.7.x/admin-api/db-encryption.md b/app/gateway/2.7.x/admin-api/db-encryption.md new file mode 100644 index 000000000000..f749240ac86e --- /dev/null +++ b/app/gateway/2.7.x/admin-api/db-encryption.md @@ -0,0 +1,169 @@ +--- +title: Keyring & Data Encryption +badge: enterprise +--- + +## View Keyring +**Endpoint** + +
    /keyring
    + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "active": "RfsDJ2Ol", + "ids": [ + "RfsDJ2Ol", + "xSD219lH" + ] +} + +``` + +## View Active Key +**Endpoint** + +
    /keyring/active
    + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "id": "RfsDJ2Ol" +} + +``` + +## Export Keyring + +*This endpoint is only available with the `cluster` keyring strategy.* + +*The endpoint requires that the `keyring_public_key` and `keyring_private_key` Kong configuration values are defined.* + +**Endpoint** + +
    /keyring/export
    + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": "..." +} +``` + +## Import Exported Keyring + +*This endpoint is only available with the `cluster` keyring strategy.* + +*The endpoint requires that the `keyring_public_key` and `keyring_private_key` Kong configuration values are defined.* + +**Endpoint** + +
    /keyring/import
    + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `data` | Base64-encoded keyring export material. | + + +**Response** + +``` +HTTP 201 Created +``` + +## Import Key + +*This endpoint is only available with the `cluster` keyring strategy.* + +*The endpoint requires that the `keyring_public_key` and `keyring_private_key` Kong configuration values are defined.* + +**Endpoint** + +
    /keyring/import/raw
    + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `id` | 8-byte key identifier. | +| `data` | Base64-encoded keyring export material. | + + +**Response** + +``` +HTTP 201 Created +``` + +## Generate New Key + +*This endpoint is only available with the `cluster` keyring strategy.* + +**Endpoint** + +
    /keyring/generate
    + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "id": "500pIquV", + "key": "3I23Ben5m7qKcCA/PK7rnsNeD3kI4IPtA6ki7YjAgKA=" +} +``` + +## Remove Key from Keyring + +*This endpoint is only available with the `cluster` keyring strategy.* + +**Endpoint** + +
    /keyring/remove
    + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `key` | 8-byte key identifier. | + + +**Response** + +``` +HTTP 204 No Content +``` + +## Sync Keyring with Vault Endpoint + +*This endpoint is only available with the `vault` keyring strategy.* + +**Endpoint** + +
    /keyring/vault/sync
    + +**Response** + +``` +HTTP 204 No Content +``` diff --git a/app/gateway/2.7.x/admin-api/event-hooks/examples.md b/app/gateway/2.7.x/admin-api/event-hooks/examples.md new file mode 100644 index 000000000000..69a57ce5d7cb --- /dev/null +++ b/app/gateway/2.7.x/admin-api/event-hooks/examples.md @@ -0,0 +1,389 @@ +--- +title: Event Hooks Examples +badge: enterprise +--- + +{% include_cached /md/enterprise/event-hooks-intro.md %} + +## Webhook + +Webhook event hooks make JSON POST requests to a provided URL with the event data as a payload. +For this example, we will use a site that is helpful for testing webhooks: [https://webhook.site](https://webhook.site). + +To create a webhook event hook: + +1. Generate a URL by navigating to [https://webhook.site](https://webhook.site) in your web browser. +2. Select **Copy to clipboard** next to **Your unique URL**. +3. Create a webhook event hook on the `consumers` event (Kong entity the event hook will listen to for events), + on the `crud` source (action that triggers logging), and the URL you copied from step 2 using the following HTTP request: +{% capture the_code %} +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/event-hooks \ +-d source=crud \ +-d event=consumers \ +-d handler=webhook \ +-d config.url= +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/event-hooks \ +source=crud \ +event=consumers \ +handler=webhook \ +config.url= +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code | indent }} + +4. Navigate to the URL from step 2. You should see a POST request, of type `ping`, notifying our webhook endpoint + about the creation of this webhook. +5. In Kong Manager or Kong Admin API, add a consumer from any workspace. + +{% capture the_code2 %} +{% navtabs %} +{% navtab Kong Manager %} + +1. Select the workspace. +2. Select **Consumers** in the left navigation. +3. Select the **New Consumer** button. +4. Enter a **Username**. +5. (Optional) Enter a **Custom ID** and any **Tags**. +6. Select the **Create** button. + +{% endnavtab %} +{% navtab Admin API %} + +Create a consumer, Ada Lovelace, by making the following HTTP request to your instance of the Kong Admin API: + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers \ +-d username="Ada Lovelace" +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/consumers \ +username="Ada Lovelace" +``` +{% endnavtab %} +{% endnavtabs %} + +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code2 | indent }} + +6. Check the URL from the [https://webhook.site](https://webhook.site) page. + You should see an entry with data for the new consumer in its payload. + + ```json + { + "source": "crud", + "entity": { + "created_at": 1627581878, + "type": 0, + "username": "Ada Lovelace", + "id": "0fd2319f-13ea-4582-a448-8d11893026a8" + }, + "event": "consumers", + "operation": "create", + "schema": "consumers" + } + ``` + +## Custom webhook + +Custom webhook event hooks are fully customizable requests. Custom webhooks are useful for building direct +integration with a service. Because custom webhooks are fully configurable, they have more complex configurations. +Custom webhooks support Lua templating on a configurable body, form payload, and headers. For a list of +possible fields for templating, see the [sources](/gateway/{{ page.release }}/admin-api/event-hooks/reference/#list-all-sources) endpoint. + +The following example sends a message to Slack any time a new administrator is invited to {{site.base_gateway}}. +Slack allows for [incoming webhooks](https://slack.com/help/articles/115005265063-Incoming-webhooks-for-Slack#set-up-incoming-webhooks) +and we can use these to build an integration with Kong's event hooks features. + +To create a custom webhook event hook: + +1. [Create an app in Slack.](https://api.slack.com/apps?new_app=1) +2. Activate incoming webhooks in the settings for your new app. +3. Select to **Add New Webhook to Workspace**, select the channel where you wish to receive notices, and select **Allow**. +4. Copy the **Webhook URL**, for example `https://hooks.slack.com/services/foo/bar/baz`. +5. Create a webhook event hook on the `admins` event (Kong entity the event hook will listen to for events), + and the `crud` source (action that triggers logging), and format the payload as, {% raw %}"Admin account \`{{ entity.username }}\` {{ operation }}d; e-mail address set to \`{{ entity.email }}\`"{% endraw %}, using the following HTTP request: + +{% capture the_code3 %} +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/event-hooks \ +-d source=crud \ +-d event=admins \ +-d handler=webhook-custom \ +-d config.method=POST \ +-d config.url= \ +-d config.headers.content-type="application/json" \ +-d config.payload.text={% raw %}"Admin account \`{{ entity.username }}\` {{ operation}}d; email address set to \`{{ entity.email }}\`"{% endraw %} +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/event-hooks \ +source=crud \ +event=admins \ +handler=webhook-custom \ +config.method=POST \ +config.url= \ +config.headers.content-type="application/json" \ +config.payload.text={% raw %}"Admin account \`{{ entity.username }}\` {{ operation}}d; email address set to \`{{ entity.email }}\`"{% endraw %} +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code3 | indent }} + +6. Turn on RBAC. + +{% capture anInclude %} +{% include_cached /md/enterprise/turn-on-rbac.md %} +{% endcapture %} +{{ anInclude | indent }} + +7. Invite an Admin using Kong Manager or the Kong Admin API. + +{% capture the_code2 %} +{% navtabs %} +{% navtab Kong Manager %} + +1. Go to Kong Manager, or reload the page if you already have it open and you will see a login screen. +2. Log in to Kong Manager with the built-in Super Admin account, `kong_admin`, and its password. + This is the initial `KONG_PASSWORD` you used when you ran migrations during installation. +3. From the **Teams > Admins** tab, click **Invite Admin**. +4. Enter the new administrator's **Email** address and **Username**. +5. Click **Invite Admin** to send the invite. + At this point in the getting started guide, you likely haven’t set up SMTP yet, so no email will be sent. + +{% endnavtab %} +{% navtab Admin API %} + +Create an admin, Arya Stark, by making the following HTTP request to your instance of the Kong Admin API: + +{:.note} +> **Note:** Replace `` with your `kong_admin` password. This is the initial + `KONG_PASSWORD` you used when you ran migrations during installation. + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/admins \ +-d username="Arya Stark" \ +-d email=arya@gameofthrones.com \ +-H Kong-Admin-Token: +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/admins \ +username="Arya Stark" \ +email=arya@gameofthrones.com \ +Kong-Admin-Token= +``` +{% endnavtab %} +{% endnavtabs %} + +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code2 | indent }} + +Afterwards, you should receive a message in the Slack channel you selected with the message you included as the +`config.payload.text`. + +## Log + +Log event hooks log the specified event and content of the payload into the {{site.base_gateway}} logs. + +To create a log event hook: + +1. Create a log event hook on the `consumers` event (Kong entity the event hook will listen to for events) + and on the `crud` source (action that triggers logging) using the following HTTP request: + +{% capture the_code5 %} +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/event-hooks \ +-d source=crud \ +-d event=consumers \ +-d handler=log +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/event-hooks \ +source=crud \ +event=consumers \ +handler=log +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code5 | indent }} + +2. In Kong Manager or Kong Admin API, add a consumer from any workspace. + +{% capture the_code6 %} +{% navtabs %} +{% navtab Kong Manager %} + +1. Select the workspace. +2. Select **Consumers** in the left navigation. +3. Select the **New Consumer** button. +4. Enter a **Username**. +5. (Optional) Enter a **Custom ID** and any **Tags**. +6. Select the **Create** button. + +{% endnavtab %} +{% navtab Admin API %} + +Create a consumer, Elizabeth Bennet, by making the following HTTP request to your instance of the Kong Admin API: + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers \ +-d username="Elizabeth Bennet" +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/consumers \ +username="Elizabeth Bennet" +``` +{% endnavtab %} +{% endnavtabs %} + +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code6 | indent }} + +3. You should see an entry with data for the new consumer in the payload in Kong's error log, + which is typically accessible at `/usr/local/kong/logs/error.log`. + + ```log + 172.19.0.1 - - [29/Jul/2021:15:57:15 +0000] "POST /consumers HTTP/1.1" 409 147 "-" "HTTPie/2.4.0" + 2021/07/29 15:57:26 [notice] 68854#0: *819021 +--------------------------------------------------+, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 |[kong] event_hooks.lua:?:452 "log callback: " { "consumers", "crud", {|, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | entity = { |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | created_at = 1627574246, |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | id = "4757bd6b-8d54-4b08-bf24-01e346a9323e",|, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | type = 0, |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | username = "Elizabeth Bennet" |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | }, |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | operation = "create", |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | schema = "consumers" |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 | }, 68854 } |, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + 2021/07/29 15:57:26 [notice] 68854#0: *819021 +--------------------------------------------------+, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + + ``` + +## Lambda + +The lambda event hook allows you to write completely custom logic in Lua code and +hook it into a variety of Kong events. The following example writes a log entry +any time a consumer changes, but conditionally and with custom formatting. + +{:.important} +> The lambda event hook type is extremely powerful: you can write completely custom logic to handle any use case you want. +However, it’s [restricted by default through the sandbox.](/gateway/{{ page.release }}/reference/configuration/#untrusted_lua). This +sandbox is put in place to keep users safe: it’s easy to inadvertently add unsafe libraries/objects into the sandbox +and leave the {{site.base_gateway}} exposed to security vulnerabilities. Use caution before modifying these sandbox settings. + +To create a lambda event hook: + +1. Create a Lua script to load into the lambda event hook and save it to a file named `lambda.lua` on your home directory. + + ```lua + return function (data, event, source, pid) + local user = data.entity.username + error("Event hook on consumer " .. user .. "") + end + ``` +2. Create a lambda event hook on the `consumers` event (Kong entity the event hook will listen to for events) + and on the `crud` source (action that triggers logging) using the following HTTP request: + +{% capture the_code7 %} +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/event-hooks \ +-d source=crud \ +-d event=consumers \ +-d handler=lambda \ +-F config.functions='return function (data, event, source, pid) local user = data.entity.username error("Event hook on consumer " .. user .. "")end' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/event-hooks \ +source=crud \ +event=consumers \ +handler=lambda \ +config.functions[]=@~/lambda.lua +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code7 | indent }} + +3. In Kong Manager or Kong Admin API, add a consumer to any workspace. + +{% capture the_code8 %} +{% navtabs %} +{% navtab Kong Manager %} + +1. Select the workspace. +2. Select **Consumers** in the left navigation. +3. Select the **New Consumer** button. +4. Enter a **Username**. +5. (Optional) Enter a **Custom ID** and any **Tags**. +6. Select the **Create** button. + +{% endnavtab %} +{% navtab Admin API %} + +Create a consumer, Lois Lane, by making the following HTTP request to your instance of the Kong Admin API: + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers \ +-d username="Lois Lane" +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/consumers \ +username="Lois Lane" +``` +{% endnavtab %} +{% endnavtabs %} + +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ the_code8 | indent }} + +3. You should see an entry "Event hook on consumer Lois Lane" in Kong's error log, + which is typically accessible at `/usr/local/kong/logs/error.log`. + + ```log + 2021/07/29 21:52:54 [error] 114#0: *153047 [kong] event_hooks.lua:190 [string "return function (data, event, source, pid)..."]:3: Event hook on consumer Lois Lane, context: ngx.timer, client: 172.19.0.1, server: 0.0.0.0:8001 + ``` diff --git a/app/gateway/2.7.x/admin-api/event-hooks/reference.md b/app/gateway/2.7.x/admin-api/event-hooks/reference.md new file mode 100644 index 000000000000..e4903e85f248 --- /dev/null +++ b/app/gateway/2.7.x/admin-api/event-hooks/reference.md @@ -0,0 +1,427 @@ +--- +title: Event Hooks Reference +badge: enterprise +--- + +{:.important} +> **Important:** Before you can use event hooks for the first time, Kong needs to be +reloaded. + +{% include_cached /md/enterprise/event-hooks-intro.md %} + +{:.note} +> **Note:** Event hooks do not work with {{site.konnect_short_name}} yet. + +## List all event hooks + +**Endpoint** + +
    /event-hooks
    + +**Response** + +```json +{ + "data": [ + { + "config": { + "body": null, + "body_format": true, + "headers": { + "content-type": "application/json" + }, + "headers_format": false, + "method": "POST", + "payload": { + "text": "{% raw %}Admin account \`{{ entity.username }}\` {{ operation}}d; email address set to \`{{ entity.email }}\`{% endraw %}" + }, + "payload_format": true, + "secret": null, + "ssl_verify": false, + "url": "https://hooks.slack.com/services/foo/bar/baz" + }, + "created_at": 1627588552, + "event": "admins", + "handler": "webhook-custom", + "id": "937df175-3db2-4e6d-8aa1-d95c94a76089", + "on_change": null, + "snooze": null, + "source": "crud" + }, + { + "config": { + "headers": {}, + "secret": null, + "ssl_verify": false, + "url": "https://webhook.site/a1b2c3-d4e5-g6h7-i8j9-k1l2m3n4o5p6" + }, + "created_at": 1627581575, + "event": "consumers", + "handler": "webhook", + "id": "c57340ab-9fed-40fd-bb7e-1cef8d37c2df", + "on_change": null, + "snooze": null, + "source": "crud" + }, + { + "config": { + "functions": [ + "return function (data, event, source, pid)\n local user = data.entity.username\n error(\"Event hook on consumer \" .. user .. \"\")\nend\n" + ] + }, + "created_at": 1627595513, + "event": "consumers", + "handler": "lambda", + "id": "c9fdd58d-5416-4d3a-9467-51e5cfe4ca0e", + "on_change": null, + "snooze": null, + "source": "crud" + } + ], + "next": null +} +``` + +## List all sources + +Sources are the actions that trigger the event hook. The `/sources` JSON output follows the following pattern: +- 1st level = The source, which is the action that triggers the event hook. +- 2nd level = The event, which is the Kong entity the event hook will listen to for events. +- 3rd level = The available template parameters for use in webhook-custom payloads. + +For instance, in the example below `balancer` is the source, `health` is the event, and `upstream_id`, +`ip`, `port`, `hostname`, and `health` are the available template parameters. + +**Endpoint** + +
    /event-hooks/sources/
    + +**Response** + +```json +{ + "data": { + "balancer": { + "health": { + "fields": [ + "upstream_id", + "ip", + "port", + "hostname", + "health" + ] + } + }, + "crud": { + "acls": { + "fields": [ + "operation", + "entity", + "old_entity", + "schema" + ] + }, + . . . + + "rate-limiting-advanced": { + "rate-limit-exceeded": { + "description": "Run an event when a rate limit has been exceeded", + "fields": [ + "consumer", + "ip", + "service", + "rate", + "limit", + "window" + ], + "unique": [ + "consumer", + "ip", + "service" + ] + } + } + } +} +``` + +{:.note} +> **Note:** The response has been shortened because it is too long to include in its entirety. +The ellipsis in the center of the response represents the missing content. + +## List all events for a source + +Events are the Kong entities the event hook will listen to for events. With this endpoint you +can list all of the events associated with a particular source. + +
    /event-hooks/sources/{source}/
    + +The following response lists all of the events for the `dao:crud` source. + +**Response** + +```json +{ + "data": { + "create": { + "fields": [ + "operation", + "entity", + "old_entity", + "schema" + ] + }, + "delete": { + "fields": [ + "operation", + "entity", + "old_entity", + "schema" + ] + }, + "update": { + "fields": [ + "operation", + "entity", + "old_entity", + "schema" + ] + } + } +} +``` + +## Add a webhook + +**Endpoint** + +
    /event-hooks
    + +**Request Body** + +| Attribute | Description | +| ---------: | -------- | +| `event`
    *optional* | A string describing the Kong entity the event hook will listen to for events. | +| `handler`
    *required* | A string describing one of four handler options: webhook, webhook-custom, log, or lambda. | +| `source`
    *required* | A string describing the action that triggers the event hook. | +| `snooze`
    *optional* | An optional integer describing the time in seconds to delay an event trigger to avoid spamming an integration. | +| `on_change`
    *optional* | An optional boolean indicating whether to trigger an event when key parts of a payload have changed. | +| `config.url`
    *required* | The URL the JSON POST request is made to with the event data as the payload. | +| `config.headers`
    *optional* | An object defining additional HTTP headers to send in the webhook request, for example `{"X-Custom-Header": "My Value"}`.| +| `config.secret`
    *optional* | An optional string used to sign the remote webhook for remote verification. When set, Kong will sign the body of the event hook with HMAC-SHA1 and include it in a header, `x-kong-signature`, to the remote endpoint. | +| `config.ssl_verify`
    *optional* | A boolean indicating whether to verify the SSL certificate of the remote HTTPS server where the event hook will be sent. The default is `false`. | + +**Response** + +```json +{ + "config": { + "headers": {}, + "secret": null, + "ssl_verify": false, + "url": "https://webhook.site/a1b2c3-d4e5-g6h7-i8j9-k1l2m3n4o5p6" + }, + "created_at": 1627581575, + "event": "consumers", + "handler": "webhook", + "id": "c57340ab-9fed-40fd-bb7e-1cef8d37c2df", + "on_change": null, + "snooze": null, + "source": "crud" +} +``` + +## Add a custom webhook + +**Endpoint** + +
    /event-hooks
    + +**Request Body** + +| Attribute | Description | +| ---------: | -------- | +| `event`
    *optional* | A string describing the Kong entity the event-hook will listen to for events. | +| `handler`
    *required* | A string describing one of four handler options: webhook, webhook-custom, log, or lambda. | +| `source`
    *required* | A string describing the action that triggers the event hook. | +| `snooze`
    *optional* | An optional integer describing the time in seconds to delay an event trigger to avoid spamming an integration. | +| `on_change`
    *optional* | An optional boolean indicating whether to trigger an event when key parts of a payload have changed. | +| `config.url`
    *required* | The URL the JSON POST request is made to with the event data as the payload. | +| `config.method`
    *required* | The HTTP method used to create the custom webhook. | +| `config.payload`
    *optional* | An object that includes key/value pairs that describe the configurable payload body. Supports templating. The full list of available template parameters can be found in the `/sources` API output, under the `fields` JSON object. | +| `config.payload_format`
    *optional* | A optional boolean (defaults to `true`) indicating whether to format the `config.payload` with resty templating. When set to `false`, the payload is sent as a raw object. | +| `config.body`
    *optional* | An optional string sent in the remote request. | +| `config.body_format`
    *optional* | An optional boolean (defaults to `true`) indicating whether to format the `config.body` with resty templating. When set to `false`, the body is sent as a raw object. To see all the available parameters defined for a specific `source`, check the source fields displayed by the `/event-hooks/source` endpoint. | +| `config.headers` | An object defining additional HTTP headers to send in the webhook request, for example `{"Content-type": "application/json", "X-Custom-Header": "My Value"}`. | +| `config.headers_format`
    *optional* | An optional boolean (defaults to `false`) indicating whether to format the `config.headers` with resty templating. When set to `true`, the `config.headers` value will be treated as a template. To see all the available parameters defined for a specific `source`, check the source fields displayed by the `/event-hooks/sources` endpoint. | +| `config.secret`
    *optional* | An optional string used to sign the remote webhook for remote verification. When set, Kong will sign the body of the event hook with HMAC-SHA1 and include it in a header, `x-kong-signature`, to the remote endpoint. | +| `config.ssl_verify`
    *optional* | A boolean indicating whether to verify the SSL certificate of the remote HTTPS server where the event hook will be sent. The default value is `false`. | + +**Response** + +```json +{ + "config": { + "body": null, + "body_format": true, + "headers": { + "content-type": "application/json" + }, + "headers_format": false, + "method": "POST", + "payload": { + "text": "Admin account `{{ entity.username }}` {{ operation }}d; email address set to `{{ entity.email }}`" + }, + "payload_format": true, + "secret": null, + "ssl_verify": false, + "url": "https://hooks.slack.com/services/foo/bar/baz" + }, + "created_at": 1627588552, + "event": "admins", + "handler": "webhook-custom", + "id": "937df175-3db2-4e6d-8aa1-d95c94a76089", + "on_change": null, + "snooze": null, + "source": "crud" +} +``` + +## Add a log event hook + +**Endpoint** + +
    /event-hooks
    + +**Request Body** + +| Attribute | Description | +| ---------: | -------- | +| `event`
    *optional* | A string describing the Kong entity the event hook will listen to for events. | +| `handler`
    *required* | A string describing one of four handler options: webhook, webhook-custom, log, or lambda. | +| `source`
    *required* | A string describing the action that triggers the event hook. | +| `snooze`
    *optional* | An optional integer describing the time in seconds to delay an event trigger to avoid spamming an integration. | +| `on_change`
    *optional* | An optional boolean indicating whether to trigger an event when key parts of a payload have changed. | + +**Response** + +```json +{ + "config": {}, + "on_change": null, + "created_at": 1627346155, + "snooze": null, + "id": "13a16f91-68b6-4384-97f7-d02763a551ac", + "handler": "log", + "source": "crud", + "event": "routes" +} +``` + +## Add a lambda event hook + +**Endpoint** + +
    /event-hooks
    + +**Request Body** + +| Attribute | Description | +| ---------: | -------- | +| `event`
    *optional* | A string describing the Kong entity the event hook will listen to for events. | +| `handler`
    *required* | A string describing one of four handler options: webhook, webhook-custom, log, or lambda. | +| `source`
    *required* | A string describing the action that triggers the event hook. | +| `snooze`
    *optional* | An optional integer describing the time in seconds to delay an event trigger to avoid spamming an integration. | +| `on_change`
    *optional* | An optional boolean indicating whether to trigger an event when key parts of a payload have changed. | +| `config.functions`
    *required* | An array of Lua code functions to execute on the event hook. | + +**Response** + +```json +{ + "config": { + "functions": [ + "return function (data, event, source, pid)\n local user = data.entity.username\n error(\"Event hook on consumer \" .. user .. \"\")\nend\n" + ] + }, + "created_at": 1627595513, + "event": "consumers", + "handler": "lambda", + "id": "c9fdd58d-5416-4d3a-9467-51e5cfe4ca0e", + "on_change": null, + "snooze": null, + "source": "crud" +} +``` + +## Test an event hook + +It's useful to manually trigger an event hook without provoking the event to be triggered. +For instance, you might want to test the integration, or see if your hook's service is receiving a payload from Kong. + +POST any data to `/event-hooks/:id-of-hook/test`, and the `/test` endpoint executes the with the provided data as the event payload. + +**Endpoint** + +
    /event-hooks/{event-hook-id}/test
    + +**Response** + +```json +{ + "data": { + "consumer": { + "username": "Jane Austen" + }, + "event": "consumers", + "source": "crud" + }, + "result": { + "body": "", + "headers": { + "Cache-Control": "no-cache, private", + "Content-Type": "text/plain; charset=UTF-8", + "Date": "Fri, 30 Jul 2021 16:07:09 GMT", + "Server": "nginx/1.14.2", + "Transfer-Encoding": "chunked", + "Vary": "Accept-Encoding", + "X-Request-Id": "f1e703a5-d22c-435c-8d5d-bc9c561ead4a", + "X-Token-Id": "1cc1c53b-f613-467f-a5c9-20d276405104" + }, + "status": 200 + } +} + +``` + +## Ping a webhook event hook + +**Endpoint** + +
    /event-hooks/{event-hook-id}/ping
    + +**Response** + +```json +{ + "source": "kong:event_hooks", + "event_hooks": { + "source": "crud", + "id": "c57340ab-9fed-40fd-bb7e-1cef8d37c2df", + "on_change": null, + "event": "consumers", + "handler": "webhook", + "created_at": 1627581575, + "config": { + "headers": { + "content-type": "application/json" + }, + "ssl_verify": false, + "url": "https://webhook.site/a1b2c3-d4e5-g6h7-i8j9-k1l2m3n4o5p6", + "secret": null + }, + "snooze": null + }, + "event": "ping" +} +``` diff --git a/app/gateway/2.7.x/admin-api/index.md b/app/gateway/2.7.x/admin-api/index.md new file mode 100644 index 000000000000..d034808ad895 --- /dev/null +++ b/app/gateway/2.7.x/admin-api/index.md @@ -0,0 +1,4115 @@ +--- +title: Admin API +toc: false + +service_body: | + Attributes | Description + ---:| --- + `name`
    *optional* | The Service name. + `retries`
    *optional* | The number of retries to execute upon failure to proxy. Default: `5`. + `protocol` | The protocol used to communicate with the upstream. Accepted values are: `"grpc"`, `"grpcs"`, `"http"`, `"https"`, `"tcp"`, `"tls"`, `"tls_passthrough"`, `"udp"`. Default: `"http"`. + `host` | The host of the upstream server. Note that the host value is case sensitive. + `port` | The upstream server port. Default: `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. Default: `60000`. + `write_timeout`
    *optional* | The timeout in milliseconds between two successive write operations for transmitting a request to the upstream server. Default: `60000`. + `read_timeout`
    *optional* | The timeout in milliseconds between two successive read operations for transmitting a request to the upstream server. Default: `60000`. + `tags`
    *optional* | An optional set of strings associated with the Service for grouping and filtering. + `client_certificate`
    *optional* | Certificate to be used as client certificate while TLS handshaking to the upstream server. With form-encoded, the notation is `client_certificate.id=`. With JSON, use "`"client_certificate":{"id":""}`. + `tls_verify`
    *optional* | Whether to enable verification of upstream server TLS certificate. If set to `null`, then the Nginx default is respected. + `tls_verify_depth`
    *optional* | Maximum depth of chain while verifying Upstream server's TLS certificate. If set to `null`, then the Nginx default is respected. Default: `null`. + `ca_certificates`
    *optional* | Array of `CA Certificate` object UUIDs that are used to build the trust store while verifying upstream server's TLS certificate. If set to `null` when Nginx default is respected. If default CA list in Nginx are not specified and TLS verification is enabled, then handshake with upstream server will always fail (because no CA are trusted). With form-encoded, the notation is `ca_certificates[]=4e3ad2e4-0bc4-4638-8e34-c84a417ba39b&ca_certificates[]=51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515`. With JSON, use an Array. + `enabled` | Whether the Service is active. If set to `false`, the proxy behavior will be as if any routes attached to it do not exist (404). Default: `true`. + `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"], + "client_certificate": {"id":"4e3ad2e4-0bc4-4638-8e34-c84a417ba39b"}, + "tls_verify": true, + "tls_verify_depth": null, + "ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"], + "enabled": true + } + +service_data: | + "data": [{ + "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": "/some_api", + "connect_timeout": 60000, + "write_timeout": 60000, + "read_timeout": 60000, + "tags": ["user-level", "low-priority"], + "client_certificate": {"id":"51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"}, + "tls_verify": true, + "tls_verify_depth": null, + "ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"], + "enabled": true + }, { + "id": "fc73f2af-890d-4f9b-8363-af8945001f7f", + "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"], + "client_certificate": {"id":"4506673d-c825-444c-a25b-602e3c2ec16e"}, + "tls_verify": true, + "tls_verify_depth": null, + "ca_certificates": ["4e3ad2e4-0bc4-4638-8e34-c84a417ba39b", "51e77dc2-8f3e-4afa-9d0e-0e3bbbcfd515"], + "enabled": true + }], + +route_body: | + Attributes | Description + ---:| --- + `name`
    *optional* | The name of the Route. Route names must be unique, and they are case sensitive. For example, there can be two different Routes named "test" and "Test". + `protocols` | An array of the protocols this Route should allow. See the [Route Object](#route-object) section for a list of accepted protocols. When set to only `"https"`, HTTP requests are answered with an upgrade error. When set to only `"http"`, HTTPS requests are answered with an error. Default: `["http", "https"]`. + `methods`
    *semi-optional* | A list of HTTP methods that match this Route. + `hosts`
    *semi-optional* | A list of domain names that match this Route. Note that the hosts value is case sensitive. 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. With form-encoded, the notation is `paths[]=/foo&paths[]=/bar`. With JSON, use an Array. + `headers`
    *semi-optional* | One or more lists of values indexed by header name that will cause this Route to match if present in the request. The `Host` header cannot be used with this attribute: hosts should be specified using the `hosts` attribute. + `https_redirect_status_code` | The status code Kong responds with when all properties of a Route match except the protocol i.e. if the protocol of the request is `HTTP` instead of `HTTPS`. `Location` header is injected by Kong if the field is set to 301, 302, 307 or 308. Accepted values are: `426`, `301`, `302`, `307`, `308`. Default: `426`. + `regex_priority`
    *optional* | A number used to choose which route resolves a given request when several routes match it using regexes simultaneously. When two routes match the path and have the same `regex_priority`, the older one (lowest `created_at`) is used. Note that the priority for non-regex routes is different (longer non-regex routes are matched before shorter ones). Default: `0`. + `strip_path` | When matching a Route via one of the `paths`, strip the matching prefix from the upstream request URL. Default: `true`. + `path_handling`
    *optional* | Controls how the Service path, Route path and requested path are combined when sending a request to the upstream. See above for a detailed description of each behavior. Accepted values are: `"v0"`, `"v1"`. Default: `"v0"`. + `preserve_host` | 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`. + `request_buffering` | Whether to enable request body buffering or not. With HTTP 1.1, it may make sense to turn this off on services that receive data with chunked transfer encoding. Default: `true`. + `response_buffering` | Whether to enable response body buffering or not. With HTTP 1.1, it may make sense to turn this off on services that send data with chunked transfer encoding. Default: `true`. + `snis`
    *semi-optional* | A list of SNIs that match this Route when using stream routing. + `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". + `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". + `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=` or `service.name=`. With JSON, use "`"service":{"id":""}` or `"service":{"name":""}`. + +route_json: | + { + "id": "d35165e2-d03e-461a-bdeb-dad0a112abfe", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-route", + "protocols": ["http", "https"], + "methods": ["GET", "POST"], + "hosts": ["example.com", "foo.test"], + "paths": ["/foo", "/bar"], + "headers": {"x-another-header":["bla"], "x-my-header":["foo", "bar"]}, + "https_redirect_status_code": 426, + "regex_priority": 0, + "strip_path": true, + "path_handling": "v0", + "preserve_host": false, + "request_buffering": true, + "response_buffering": true, + "tags": ["user-level", "low-priority"], + "service": {"id":"af8330d3-dbdc-48bd-b1be-55b98608834b"} + } + +route_data: | + "data": [{ + "id": "a9daa3ba-8186-4a0d-96e8-00d80ce7240b", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-route", + "protocols": ["http", "https"], + "methods": ["GET", "POST"], + "hosts": ["example.com", "foo.test"], + "paths": ["/foo", "/bar"], + "headers": {"x-another-header":["bla"], "x-my-header":["foo", "bar"]}, + "https_redirect_status_code": 426, + "regex_priority": 0, + "strip_path": true, + "path_handling": "v0", + "preserve_host": false, + "request_buffering": true, + "response_buffering": true, + "tags": ["user-level", "low-priority"], + "service": {"id":"127dfc88-ed57-45bf-b77a-a9d3a152ad31"} + }, { + "id": "9aa116fd-ef4a-4efa-89bf-a0b17c4be982", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "my-route", + "protocols": ["tcp", "tls"], + "https_redirect_status_code": 426, + "regex_priority": 0, + "strip_path": true, + "path_handling": "v0", + "preserve_host": false, + "request_buffering": true, + "response_buffering": true, + "snis": ["foo.test", "example.com"], + "sources": [{"port":1234, "ip":"10.1.0.0/16"}, {"ip":"10.2.2.2"}, {"port":9123}], + "destinations": [{"port":1234, "ip":"10.1.0.0/16"}, {"ip":"10.2.2.2"}, {"port":9123}], + "tags": ["admin", "high-priority", "critical"], + "service": {"id":"ba641b07-e74a-430a-ab46-94b61e5ea66b"} + }], + +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": "ec1a1f6f-2aa4-4e58-93ff-b56368f19b27", + "created_at": 1422386534, + "username": "my-username", + "custom_id": "my-custom-id", + "tags": ["user-level", "low-priority"] + } + +consumer_data: | + "data": [{ + "id": "a4407883-c166-43fd-80ca-3ca035b0cdb7", + "created_at": 1422386534, + "username": "my-username", + "custom_id": "my-custom-id", + "tags": ["user-level", "low-priority"] + }, { + "id": "01c23299-839c-49a5-a6d5-8864c09184af", + "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. Default: `null`.With form-encoded, the notation is `route.id=` or `route.name=`. With JSON, use "`"route":{"id":""}` or `"route":{"name":""}`. + `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. Default: `null`.With form-encoded, the notation is `service.id=` or `service.name=`. With JSON, use "`"service":{"id":""}` or `"service":{"name":""}`. + `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. Default: `null`.With form-encoded, the notation is `consumer.id=` or `consumer.username=`. With JSON, use "`"consumer":{"id":""}` or `"consumer":{"username":""}`. + `config`
    *optional* | The configuration properties for the Plugin which can be found on the plugins documentation page in the [Kong Hub](/hub/). + `protocols` | A list of the request protocols that will trigger this plugin. 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 only support `"tcp"` and `"tls"`. Default: `["grpc", "grpcs", "http",`` "https"]`. + `enabled` | Whether the plugin is applied. Default: `true`. + `tags`
    *optional* | An optional set of strings associated with the Plugin for grouping and filtering. + +plugin_json: | + { + "id": "ce44eef5-41ed-47f6-baab-f725cecf98c7", + "name": "rate-limiting", + "created_at": 1422386534, + "route": null, + "service": null, + "consumer": null, + "config": {"minute":20, "hour":500}, + "protocols": ["http", "https"], + "enabled": true, + "tags": ["user-level", "low-priority"] + } + +plugin_data: | + "data": [{ + "id": "02621eee-8309-4bf6-b36b-a82017a5393e", + "name": "rate-limiting", + "created_at": 1422386534, + "route": null, + "service": null, + "consumer": null, + "config": {"minute":20, "hour":500}, + "protocols": ["http", "https"], + "enabled": true, + "tags": ["user-level", "low-priority"] + }, { + "id": "66c7b5c4-4aaf-4119-af1e-ee3ad75d0af4", + "name": "rate-limiting", + "created_at": 1422386534, + "route": null, + "service": null, + "consumer": null, + "config": {"minute":20, "hour":500}, + "protocols": ["tcp", "tls"], + "enabled": true, + "tags": ["admin", "high-priority", "critical"] + }], + +certificate_body: | + Attributes | Description + ---:| --- + `cert` | PEM-encoded public certificate chain of the SSL key pair. + `key` | PEM-encoded private key of the SSL key pair. + `cert_alt`
    *optional* | PEM-encoded public certificate chain of the alternate SSL key pair. This should only be set if you have both RSA and ECDSA types of certificate available and would like Kong to prefer serving using ECDSA certs when client advertises support for it. + `key_alt`
    *optional* | PEM-encoded private key of the alternate SSL key pair. This should only be set if you have both RSA and ECDSA types of certificate available and would like Kong to prefer serving using ECDSA certs when client advertises support for it. + `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 convenience parameter: under the hood, it creates an SNI object and associates it with this certificate. To set this attribute this certificate must have a valid private key associated with it. + `passphrase`
    *optional* (Enterprise only) | To load an encrypted private key into Kong, specify the passphrase using this attribute. Kong will decrypt the private key and store it in its database. To encrypt the private key and other sensitive information in Kong's database, consider using DB encryption. + +certificate_json: | + { + "id": "7fca84d6-7d37-4a74-a7b0-93e576089a41", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "cert_alt": "-----BEGIN CERTIFICATE-----...", + "key_alt": "-----BEGIN EC PRIVATE KEY-----...", + "tags": ["user-level", "low-priority"] + } + +certificate_data: | + "data": [{ + "id": "d044b7d4-3dc2-4bbc-8e9f-6b7a69416df6", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "cert_alt": "-----BEGIN CERTIFICATE-----...", + "key_alt": "-----BEGIN EC PRIVATE KEY-----...", + "tags": ["user-level", "low-priority"] + }, { + "id": "a9b2107f-a214-47b3-add4-46b942187924", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "key": "-----BEGIN RSA PRIVATE KEY-----...", + "cert_alt": "-----BEGIN CERTIFICATE-----...", + "key_alt": "-----BEGIN EC PRIVATE KEY-----...", + "tags": ["admin", "high-priority", "critical"] + }], + +ca_certificate_body: | + Attributes | Description + ---:| --- + `cert` | PEM-encoded public certificate of the CA. + `cert_digest`
    *optional* | SHA256 hex digest of the public certificate. + `tags`
    *optional* | An optional set of strings associated with the Certificate for grouping and filtering. + +ca_certificate_json: | + { + "id": "04fbeacf-a9f1-4a5d-ae4a-b0407445db3f", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "cert_digest": "c641e28d77e93544f2fa87b2cf3f3d51...", + "tags": ["user-level", "low-priority"] + } + +ca_certificate_data: | + "data": [{ + "id": "43429efd-b3a5-4048-94cb-5cc4029909bb", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "cert_digest": "c641e28d77e93544f2fa87b2cf3f3d51...", + "tags": ["user-level", "low-priority"] + }, { + "id": "d26761d5-83a4-4f24-ac6c-cff276f2b79c", + "created_at": 1422386534, + "cert": "-----BEGIN CERTIFICATE-----...", + "cert_digest": "c641e28d77e93544f2fa87b2cf3f3d51...", + "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. The Certificate must have a valid private key associated with it to be used by the SNI object. With form-encoded, the notation is `certificate.id=`. With JSON, use "`"certificate":{"id":""}`. + +sni_json: | + { + "id": "91020192-062d-416f-a275-9addeeaffaf2", + "name": "my-sni", + "created_at": 1422386534, + "tags": ["user-level", "low-priority"], + "certificate": {"id":"a2e013e8-7623-4494-a347-6d29108ff68b"} + } + +sni_data: | + "data": [{ + "id": "147f5ef0-1ed6-4711-b77f-489262f8bff7", + "name": "my-sni", + "created_at": 1422386534, + "tags": ["user-level", "low-priority"], + "certificate": {"id":"a3ad71a8-6685-4b03-a101-980a953544f6"} + }, { + "id": "b87eb55d-69a1-41d2-8653-8d706eecefc0", + "name": "my-sni", + "created_at": 1422386534, + "tags": ["admin", "high-priority", "critical"], + "certificate": {"id":"4e8d95d4-40f2-4818-adcb-30e00c349618"} + }], + +upstream_body: | + Attributes | Description + ---:| --- + `name` | This is a hostname, which must be equal to the `host` of a Service. + `algorithm`
    *optional* | Which load balancing algorithm to use. Accepted values are: `"consistent-hashing"`, `"least-connections"`, `"round-robin"`. Default: `"round-robin"`. + `hash_on`
    *optional* | What to use as hashing input. Using `none` results in a weighted-round-robin scheme with no hashing. Accepted values are: `"none"`, `"consumer"`, `"ip"`, `"header"`, `"cookie"`. Default: `"none"`. + `hash_fallback`
    *optional* | What to use as hashing input if the primary `hash_on` does not return a hash (for example, header is missing, or no Consumer identified). Not available if `hash_on` is set to `cookie`. Accepted values are: `"none"`, `"consumer"`, `"ip"`, `"header"`, `"cookie"`. Default: `"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`. Default: `"/"`. + `slots`
    *optional* | The number of slots in the load balancer algorithm. If `algorithm` is set to `round-robin`, this setting determines the maximum number of slots. If `algorithm` is set to `consistent-hashing`, this setting determines the actual number of slots in the algorithm. Accepts an integer in the range `10`-`65536`. Default: `10000`. + `healthchecks.passive.``type`
    *optional* | Whether to perform passive health checks interpreting HTTP/HTTPS statuses, or just check for TCP connection success. In passive checks, `http` and `https` options are equivalent. Accepted values are: `"tcp"`, `"http"`, `"https"`, `"grpc"`, `"grpcs"`. Default: `"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. Default: `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. Default: `[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. + `healthchecks.passive.``unhealthy.tcp_failures`
    *optional* | Number of TCP failures in proxied traffic to consider a target unhealthy, as observed by passive health checks. Default: `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. Default: `[429, 500, 503]`. With form-encoded, the notation is `http_statuses[]=429&http_statuses[]=500`. With JSON, use an Array. + `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. Default: `0`. + `healthchecks.passive.``unhealthy.timeouts`
    *optional* | Number of timeouts in proxied traffic to consider a target unhealthy, as observed by passive health checks. Default: `0`. + `healthchecks.active.``http_path`
    *optional* | Path to use in GET HTTP request to run as a probe on active health checks. Default: `"/"`. + `healthchecks.active.``timeout`
    *optional* | Socket timeout for active health checks (in seconds). Default: `1`. + `healthchecks.active.``concurrency`
    *optional* | Number of targets to check concurrently in active health checks. Default: `10`. + `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.type`
    *optional* | Whether to perform active health checks using HTTP or HTTPS, or just attempt a TCP connection. Accepted values are: `"tcp"`, `"http"`, `"https"`, `"grpc"`, `"grpcs"`. Default: `"http"`. + `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. Default: `0`. + `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. Default: `[200, 302]`. With form-encoded, the notation is `http_statuses[]=200&http_statuses[]=302`. With JSON, use an Array. + `healthchecks.active.``healthy.successes`
    *optional* | Number of successes in active probes (as defined by `healthchecks.active.healthy.http_statuses`) to consider a target healthy. Default: `0`. + `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. Default: `true`. + `healthchecks.active.``unhealthy.tcp_failures`
    *optional* | Number of TCP failures in active probes to consider a target unhealthy. Default: `0`. + `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. Default: `[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.http_failures`
    *optional* | Number of HTTP failures in active probes (as defined by `healthchecks.active.unhealthy.http_statuses`) to consider a target unhealthy. Default: `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. Default: `0`. + `healthchecks.active.``unhealthy.timeouts`
    *optional* | Number of timeouts in active probes to consider a target unhealthy. Default: `0`. + `healthchecks.threshold`
    *optional* | The minimum percentage of the upstream's targets' weight that must be available for the whole upstream to be considered healthy. Default: `0`. + `tags`
    *optional* | An optional set of strings associated with the Upstream for grouping and filtering. + `host_header`
    *optional* | The hostname to be used as `Host` header when proxying requests through Kong. + `client_certificate`
    *optional* | If set, the certificate to be used as client certificate while TLS handshaking to the upstream server.With form-encoded, the notation is `client_certificate.id=`. With JSON, use "`"client_certificate":{"id":""}`. + +upstream_json: | + { + "id": "58c8ccbb-eafb-4566-991f-2ed4f678fa70", + "created_at": 1422386534, + "name": "my-upstream", + "algorithm": "round-robin", + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/", + "slots": 10000, + "healthchecks": { + "passive": { + "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] + }, + "unhealthy": { + "tcp_failures": 0, + "http_statuses": [429, 500, 503], + "http_failures": 0, + "timeouts": 0 + } + }, + "active": { + "http_path": "/", + "timeout": 1, + "concurrency": 10, + "https_sni": "example.com", + "type": "http", + "healthy": { + "interval": 0, + "http_statuses": [200, 302], + "successes": 0 + }, + "https_verify_certificate": true, + "unhealthy": { + "tcp_failures": 0, + "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505], + "http_failures": 0, + "interval": 0, + "timeouts": 0 + } + }, + "threshold": 0 + }, + "tags": ["user-level", "low-priority"], + "host_header": "example.com", + "client_certificate": {"id":"ea29aaa3-3b2d-488c-b90c-56df8e0dd8c6"} + } + +upstream_data: | + "data": [{ + "id": "4fe14415-73d5-4f00-9fbc-c72a0fccfcb2", + "created_at": 1422386534, + "name": "my-upstream", + "algorithm": "round-robin", + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/", + "slots": 10000, + "healthchecks": { + "passive": { + "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] + }, + "unhealthy": { + "tcp_failures": 0, + "http_statuses": [429, 500, 503], + "http_failures": 0, + "timeouts": 0 + } + }, + "active": { + "http_path": "/", + "timeout": 1, + "concurrency": 10, + "https_sni": "example.com", + "type": "http", + "healthy": { + "interval": 0, + "http_statuses": [200, 302], + "successes": 0 + }, + "https_verify_certificate": true, + "unhealthy": { + "tcp_failures": 0, + "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505], + "http_failures": 0, + "interval": 0, + "timeouts": 0 + } + }, + "threshold": 0 + }, + "tags": ["user-level", "low-priority"], + "host_header": "example.com", + "client_certificate": {"id":"a3395f66-2af6-4c79-bea2-1b6933764f80"} + }, { + "id": "885a0392-ef1b-4de3-aacf-af3f1697ce2c", + "created_at": 1422386534, + "name": "my-upstream", + "algorithm": "round-robin", + "hash_on": "none", + "hash_fallback": "none", + "hash_on_cookie_path": "/", + "slots": 10000, + "healthchecks": { + "passive": { + "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] + }, + "unhealthy": { + "tcp_failures": 0, + "http_statuses": [429, 500, 503], + "http_failures": 0, + "timeouts": 0 + } + }, + "active": { + "http_path": "/", + "timeout": 1, + "concurrency": 10, + "https_sni": "example.com", + "type": "http", + "healthy": { + "interval": 0, + "http_statuses": [200, 302], + "successes": 0 + }, + "https_verify_certificate": true, + "unhealthy": { + "tcp_failures": 0, + "http_statuses": [429, 404, 500, 501, 502, 503, 504, 505], + "http_failures": 0, + "interval": 0, + "timeouts": 0 + } + }, + "threshold": 0 + }, + "tags": ["admin", "high-priority", "critical"], + "host_header": "example.com", + "client_certificate": {"id":"f5a9c0ca-bdbb-490f-8928-2ca95836239a"} + }], + +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 load balancer (`0`-`65535`). If the hostname resolves to an SRV record, the `weight` value will be overridden by the value from the DNS record. Default: `100`. + `tags`
    *optional* | An optional set of strings associated with the Target for grouping and filtering. + +target_json: | + { + "id": "173a6cee-90d1-40a7-89cf-0329eca780a6", + "created_at": 1422386534, + "upstream": {"id":"bdab0e47-4e37-4f0b-8fd0-87d95cc4addc"}, + "target": "example.com:8000", + "weight": 100, + "tags": ["user-level", "low-priority"] + } + +target_data: | + "data": [{ + "id": "f00c6da4-3679-4b44-b9fb-36a19bd3ae83", + "created_at": 1422386534, + "upstream": {"id":"0c61e164-6171-4837-8836-8f5298726d53"}, + "target": "example.com:8000", + "weight": 100, + "tags": ["user-level", "low-priority"] + }, { + "id": "5027BBC1-508C-41F8-87F2-AB1801E9D5C3", + "created_at": 1422386534, + "upstream": {"id":"68FDB05B-7B08-47E9-9727-AF7F897CFF1A"}, + "target": "example.com:8000", + "weight": 100, + "tags": ["admin", "high-priority", "critical"] + }], + + +--- + +{{site.base_gateway}} 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. + +--- + + +## DB-less Mode + + +In [DB-less mode](../reference/db-less-and-declarative-config/), the 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 Kong 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. + +In DB-less mode, you configure {{site.base_gateway}} declaratively. +Therefore, the Admin API is mostly read-only. The only tasks it can perform are all +related to handling the declarative config, including: + +* [Validating configurations against schemas](#validate-a-configuration-against-a-schema) +* [Validating plugin configurations against schemas](#validate-a-plugin-configuration-against-the-schema) +* [Reloading the declarative configuration](#reload-declarative-configuration) +* [Setting a target's health status in the load balancer](#set-target-as-healthy) + + +--- + + +## Declarative Configuration + + +Loading the declarative configuration of entities into {{site.base_gateway}} +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, see the +[declarative configuration](../reference/db-less-and-declarative-config/) documentation. + + +
    /config
    + +{:.indent} +Attributes | Description +---:| --- +`config`
    **required** | The config data (in YAML or JSON format) to be loaded. + + +#### Request Querystring Parameters + +Attributes | Description +---:| --- +`check_hash`
    *optional* | If set to 1, Kong will compare the hash of the input config data against that of the previous one. If the configuration is identical, it will not reload it and will return HTTP 304. + + +#### Response + +``` +HTTP 200 OK +``` + +``` json +{ + { + "services": [], + "routes": [] + } +} +``` + +The response contains a list of all the entities that were parsed from the +input file. + +--- + + +## Supported Content Types + +The Admin API accepts 3 content types on every endpoint: + +- **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" + } +} +``` + +An example adding a Route to a Service named `test-service`: + +``` +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -H "Content-Type: application/json" \ + -d '{"name": "test-route", "paths": [ "/path/one", "/path/two" ]}' +``` + +- **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 +``` + +When specifying arrays, send the values in order, or use square brackets (numbering +inside the brackets is optional but if provided it must be 1-indexed, and +consecutive). An example Route added to a Service named `test-service`: + +``` +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -d "name=test-route" \ + -d "paths[1]=/path/one" \ + -d "paths[2]=/path/two" +``` + +The following two examples are identical to the one above, but less explicit: +``` +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -d "name=test-route" \ + -d "paths[]=/path/one" \ + -d "paths[]=/path/two" + +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -d "name=test-route" \ + -d "paths=/path/one" \ + -d "paths=/path/two" +``` + + +- **multipart/form-data** + +Similar to URL-encoded, this content type uses dotted keys to reference nested +objects. Here is an example of sending a Lua file to the pre-function Kong plugin: + +``` +curl -i -X POST http://localhost:8001/services/plugin-testing/plugins \ + -F "name=pre-function" \ + -F "config.access=@custom-auth.lua" +``` + +When specifying arrays for this content-type, the array indices must be specified. +An example Route added to a Service named `test-service`: + +``` +curl -i -X POST http://localhost:8001/services/test-service/routes \ + -F "name=test-route" \ + -F "paths[1]=/path/one" \ + -F "paths[2]=/path/two" +``` + +--- + +## Information Routes + + + +### Retrieve Node Information +{:.badge .dbless} + +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. + + +--- + +### Check Endpoint Or Entity Existence +{:.badge .dbless} + +Similar to `HTTP GET`, but does not return the body. Returns `HTTP 200` when the endpoint exits or `HTTP 404` when it does not. Other status codes are possible. + +
    /<any-endpoint>
    + +#### Response + +``` +HTTP 200 OK +``` + +```http +Access-Control-Allow-Origin: * +Content-Length: 11389 +Content-Type: application/json; charset=utf-8 +X-Kong-Admin-Latency: 1 +``` + + +--- + +### List Http Methods by Endpoint +{:.badge .dbless} + +List all the supported `HTTP` methods by an endpoint. This can also be used with a `CORS` preflight request. + +
    /<any-endpoint>
    + +#### Response + +``` +HTTP 204 No Content +``` + +```http +Access-Control-Allow-Headers: Content-Type +Access-Control-Allow-Methods: GET, HEAD, OPTIONS +Access-Control-Allow-Origin: * +Allow: GET, HEAD, OPTIONS +``` + + +--- + +### List Available Endpoints +{:.badge .dbless} + +List all available endpoints provided by the Admin API. + +
    /endpoints
    + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + "/", + "/acls", + "/acls/{acls}", + "/acls/{acls}/consumer", + "/basic-auths", + "/basic-auths/{basicauth_credentials}", + "/basic-auths/{basicauth_credentials}/consumer", + "/ca_certificates", + "/ca_certificates/{ca_certificates}", + "/cache", + "/cache/{key}", + "..." + ] +} +``` + + +--- + +### Validate A Configuration against A Schema +{:.badge .dbless} + +Check validity of a configuration against its entity schema. +This allows you to test your input before submitting a request +to the entity endpoints of the Admin API. + +Note that this only performs the schema validation checks, +checking that the input configuration is well-formed. +A requests to the entity endpoint using the given configuration +may still fail due to other reasons, such as invalid foreign +key relationships or uniqueness check failures against the +contents of the data store. + + +
    /schemas/{entity}/validate
    + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "message": "schema validation successful" +} +``` + + +--- + +### Retrieve Entity Schema +{:.badge .dbless} + +Retrieve the schema of an entity. This is useful to +understand what fields an entity accepts, and can be used for building +third-party integrations to the Kong. + + +
    /schemas/{entity name}
    + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "fields": [ + { + "id": { + "auto": true, + "type": "string", + "uuid": true + } + }, + { + "created_at": { + "auto": true, + "timestamp": true, + "type": "integer" + } + }, + ... + ] +} +``` + + +--- + +### Retrieve Plugin Schema +{:.badge .dbless} + +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. + + +
    /schemas/plugins/{plugin name}
    + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "fields": { + "hide_credentials": { + "default": false, + "type": "boolean" + }, + "key_names": { + "default": "function", + "required": true, + "type": "array" + } + } +} +``` + + +--- + +### Validate A Plugin Configuration against The Schema +{:.badge .dbless} + +Check validity of a plugin configuration against the plugins entity schema. +This allows you to test your input before submitting a request +to the entity endpoints of the Admin API. + +Note that this only performs the schema validation checks, +checking that the input configuration is well-formed. +A requests to the entity endpoint using the given configuration +may still fail due to other reasons, such as invalid foreign +key relationships or uniqueness check failures against the +contents of the data store. + + +
    /schemas/plugins/validate
    + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "message": "schema validation successful" +} +``` + + +--- + +## Health Routes + + + +### Retrieve Node Status +{:.badge .dbless} + +Retrieve usage information about a node, with some basic information +about the connections being processed by the underlying nginx process, +the status of the database connection, and node's memory usage. + +If you want to monitor the Kong process, since Kong is built on top +of nginx, every existing nginx monitoring tool or agent can be used. + + +
    /status
    + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "database": { + "reachable": true + }, + "memory": { + "workers_lua_vms": [{ + "http_allocated_gc": "0.02 MiB", + "pid": 18477 + }, { + "http_allocated_gc": "0.02 MiB", + "pid": 18478 + }], + "lua_shared_dicts": { + "kong": { + "allocated_slabs": "0.04 MiB", + "capacity": "5.00 MiB" + }, + "kong_db_cache": { + "allocated_slabs": "0.80 MiB", + "capacity": "128.00 MiB" + }, + } + }, + "server": { + "total_requests": 3, + "connections_active": 1, + "connections_accepted": 1, + "connections_handled": 1, + "connections_reading": 0, + "connections_writing": 1, + "connections_waiting": 0 + } +} +``` + +* `memory`: Metrics about the memory usage. + * `workers_lua_vms`: An array with all workers of the Kong node, where each + entry contains: + * `http_allocated_gc`: HTTP submodule's Lua virtual machine's memory + usage information, as reported by `collectgarbage("count")`, for every + active worker, i.e. a worker that received a proxy call in the last 10 + seconds. + * `pid`: worker's process identification number. + * `lua_shared_dicts`: An array of information about dictionaries that are + shared with all workers in a Kong node, where each array node contains how + much memory is dedicated for the specific shared dictionary (`capacity`) + and how much of said memory is in use (`allocated_slabs`). + These shared dictionaries have least recent used (LRU) eviction + capabilities, so a full dictionary, where `allocated_slabs == capacity`, + will work properly. However for some dictionaries, e.g. cache HIT/MISS + shared dictionaries, increasing their size can be beneficial for the + overall performance of a Kong node. + * The memory usage unit and precision can be changed using the querystring + arguments `unit` and `scale`: + * `unit`: one of `b/B`, `k/K`, `m/M`, `g/G`, which will return results + in bytes, kibibytes, mebibytes, or gibibytes, respectively. When + "bytes" are requested, the memory values in the response will have a + number type instead of string. Defaults to `m`. + * `scale`: the number of digits to the right of the decimal points when + values are given in human-readable memory strings (unit other than + "bytes"). Defaults to `2`. + You can get the shared dictionaries memory usage in kibibytes with 4 + digits of precision by doing: `GET /status?unit=k&scale=4` +* `server`: Metrics about the nginx HTTP/S server. + * `total_requests`: The total number of client requests. + * `connections_active`: The current number of active client + connections including Waiting connections. + * `connections_accepted`: The total number of accepted client + connections. + * `connections_handled`: The total number of handled connections. + Generally, the parameter value is the same as accepts unless + some resource limits have been reached. + * `connections_reading`: The current number of connections + where Kong is reading the request header. + * `connections_writing`: The current number of connections + where nginx is writing the response back to the client. + * `connections_waiting`: The current number of idle client + connections waiting for a request. +* `database`: Metrics about the database. + * `reachable`: A boolean value reflecting the state of the + database connection. Please note that this flag **does not** + reflect the health of the database itself. + + +--- + +## Tags + +Tags are strings associated to entities in Kong. + +Tags can contain almost all UTF-8 characters, with the following exceptions: + +- `,` and `/` are reserved for filtering tags with "and" and "or", so they are not allowed in tags. +- Non-printable ASCII (for example, the space character) is not allowed. + +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 +{:.badge .dbless} + +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 +{:.badge .dbless} + +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Service + +
    /services
    + + +##### Create Service Associated to a Specific Certificate + +
    /certificates/{certificate name or id}/services
    + +{:.indent} +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 Service. + + +#### Request Body + +{{ page.service_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.service_json }} +``` + + +--- + +### List Services +{:.badge .dbless} + +##### List All Services + +
    /services
    + + +##### List Services Associated to a Specific Certificate + +
    /certificates/{certificate name or id}/services
    + +{:.indent} +Attributes | Description +---:| --- +`certificate name or id`
    **required** | The unique identifier or the `name` attribute of the Certificate whose Services are to be retrieved. When using this endpoint, only Services associated to the specified Certificate will be listed. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.service_data }} + "next": "http://localhost:8001/services?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Service +{:.badge .dbless} + +##### Retrieve Service + +
    /services/{service name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to retrieve. + + +##### Retrieve Service Associated to a Specific Certificate + +
    /certificates/{certificate id}/services/{service name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to retrieve. +`service 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
    + +{:.indent} +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
    + +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Service + +
    /services/{service name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to update. + + +##### Update Service Associated to a Specific Certificate + +
    /certificates/{certificate id}/services/{service name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to update. +`service 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
    + +{:.indent} +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
    + +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Service + +
    /services/{service name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`service 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 Certificate + +
    /certificates/{certificate id}/services/{service name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to create or update. +`service 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
    + +{:.indent} +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
    + +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Service + +
    /services/{service name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to delete. + + +##### Delete Service Associated to a Specific Certificate + +
    /certificates/{certificate id}/services/{service name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to delete. +`service name or id`
    **required** | The unique identifier **or** the name of the Service to delete. + +#### 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. + +You need at least one matching rule that applies to the protocol being matched +by the Route. Depending on the protocols configured to be matched by the Route +(as defined with the `protocols` field), this means that at least one of the +following attributes must be set: + +* For `http`, at least one of `methods`, `hosts`, `headers` or `paths`; +* For `https`, at least one of `methods`, `hosts`, `headers`, `paths` or `snis`; +* For `tcp`, at least one of `sources` or `destinations`; +* For `tls`, at least one of `sources`, `destinations` or `snis`; +* For `tls_passthrough`, set `snis`; +* For `grpc`, at least one of `hosts`, `headers` or `paths`; +* For `grpcs`, at least one of `hosts`, `headers`, `paths` or `snis`. + +A route can't have both `tls` and `tls_passthrough` protocols at same time. + +#### Path handling algorithms + +`"v0"` is the behavior used in Kong 0.x and 2.x. It treats `service.path`, `route.path` and request path as +*segments* of a URL. It will always join them via slashes. Given a service path `/s`, route path `/r` +and request path `/re`, the concatenated path will be `/s/re`. If the resulting path is a single slash, +no further transformation is done to it. If it's longer, then the trailing slash is removed. + +`"v1"` is the behavior used in Kong 1.x. It treats `service.path` as a *prefix*, and ignores the initial +slashes of the request and route paths. Given service path `/s`, route path `/r` and request path `/re`, +the concatenated path will be `/sre`. + +Both versions of the algorithm detect "double slashes" when combining paths, replacing them by single +slashes. + +The following table shows the possible combinations of path handling version, strip path, and request: + +| `service.path` | `route.path` | `request` |`route.strip_path` | `route.path_handling` | request path | upstream path | +|----------------|--------------|-----------|-------------------|-----------------------|--------------|---------------| +| `/s` | `/fv0` | `req` | `false` | `v0` | `/fv0/req` | `/s/fv0/req` | +| `/s` | `/fv0` | `blank` | `false` | `v0` | `/fv0` | `/s/fv0` | +| `/s` | `/fv1` | `req` | `false` | `v1` | `/fv1/req` | `/sfv1/req` | +| `/s` | `/fv1` | `blank` | `false` | `v1` | `/fv1` | `/sfv1` | +| `/s` | `/tv0` | `req` | `true` | `v0` | `/tv0/req` | `/s/req` | +| `/s` | `/tv0` | `blank` | `true` | `v0` | `/tv0` | `/s` | +| `/s` | `/tv1` | `req` | `true` | `v1` | `/tv1/req` | `/s/req` | +| `/s` | `/tv1` | `blank` | `true` | `v1` | `/tv1` | `/s` | +| `/s` | `/fv0/` | `req` | `false` | `v0` | `/fv0/req` | `/s/fv0/req` | +| `/s` | `/fv0/` | `blank` | `false` | `v0` | `/fv0/` | `/s/fv01/` | +| `/s` | `/fv1/` | `req` | `false` | `v1` | `/fv1/req` | `/sfv1/req` | +| `/s` | `/fv1/` | `blank` | `false` | `v1` | `/fv1/` | `/sfv1/` | +| `/s` | `/tv0/` | `req` | `true` | `v0` | `/tv0/req` | `/s/req` | +| `/s` | `/tv0/` | `blank` | `true` | `v0` | `/tv0/` | `/s/` | +| `/s` | `/tv1/` | `req` | `true` | `v1` | `/tv1/req` | `/sreq` | +| `/s` | `/tv1/` | `blank` | `true` | `v1` | `/tv1/` | `/s` | + + +Routes can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.route_json }} +``` + +### Add Route + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Route + +
    /routes
    + + +##### Create Route Associated to a Specific Service + +
    /services/{service name or id}/routes
    + +{:.indent} +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 +{:.badge .dbless} + +##### List All Routes + +
    /routes
    + + +##### List Routes Associated to a Specific Service + +
    /services/{service name or id}/routes
    + +{:.indent} +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 +{:.badge .dbless} + +##### Retrieve Route + +
    /routes/{route name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`route name or id`
    **required** | The unique identifier **or** the name of the Route to retrieve. + + +##### Retrieve Route Associated to a Specific Service + +
    /services/{service name or id}/routes/{route name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to retrieve. +`route 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
    + +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Route + +
    /routes/{route name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`route name or id`
    **required** | The unique identifier **or** the name of the Route to update. + + +##### Update Route Associated to a Specific Service + +
    /services/{service name or id}/routes/{route name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to update. +`route 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
    + +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Route + +
    /routes/{route name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`route 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 Service + +
    /services/{service name or id}/routes/{route name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to create or update. +`route 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
    + +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Route + +
    /routes/{route name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`route name or id`
    **required** | The unique identifier **or** the name of the Route to delete. + + +##### Delete Route Associated to a Specific Service + +
    /services/{service name or id}/routes/{route name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to delete. +`route 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Consumer + +
    /consumers
    + + +#### Request Body + +{{ page.consumer_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.consumer_json }} +``` + + +--- + +### List Consumers +{:.badge .dbless} + +##### 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 +{:.badge .dbless} + +##### Retrieve Consumer + +
    /consumers/{consumer username or id}
    + +{:.indent} +Attributes | Description +---:| --- +`consumer 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
    + +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Consumer + +
    /consumers/{consumer username or id}
    + +{:.indent} +Attributes | Description +---:| --- +`consumer 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
    + +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Consumer + +
    /consumers/{consumer username or id}
    + +{:.indent} +Attributes | Description +---:| --- +`consumer 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
    + +{:.indent} +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Consumer + +
    /consumers/{consumer username or id}
    + +{:.indent} +Attributes | Description +---:| --- +`consumer 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](/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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Plugin + +
    /plugins
    + + +##### Create Plugin Associated to a Specific Route + +
    /routes/{route name or id}/plugins
    + +{:.indent} +Attributes | Description +---:| --- +`route name or id`
    **required** | The unique identifier or the `name` attribute of the Route that should be associated to the newly-created Plugin. + + +##### Create Plugin Associated to a Specific Service + +
    /services/{service name or id}/plugins
    + +{:.indent} +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 Plugin. + + +##### Create Plugin Associated to a Specific Consumer + +
    /consumers/{consumer name or id}/plugins
    + +{:.indent} +Attributes | Description +---:| --- +`consumer name or id`
    **required** | The unique identifier or the `name` attribute 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 +{:.badge .dbless} + +##### List All Plugins + +
    /plugins
    + + +##### List Plugins Associated to a Specific Route + +
    /routes/{route name or id}/plugins
    + +{:.indent} +Attributes | Description +---:| --- +`route name or id`
    **required** | The unique identifier or the `name` attribute 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 name or id}/plugins
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier or the `name` attribute 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 name or id}/plugins
    + +{:.indent} +Attributes | Description +---:| --- +`consumer name or id`
    **required** | The unique identifier or the `name` attribute 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 +{:.badge .dbless} + +##### Retrieve Plugin + +
    /plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`plugin id`
    **required** | The unique identifier of the Plugin to retrieve. + + +##### Retrieve Plugin Associated to a Specific Route + +
    /routes/{route name or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`route name or id`
    **required** | The unique identifier **or** the name of the Route to retrieve. +`plugin id`
    **required** | The unique identifier of the Plugin to retrieve. + + +##### Retrieve Plugin Associated to a Specific Service + +
    /services/{service name or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to retrieve. +`plugin id`
    **required** | The unique identifier of the Plugin to retrieve. + + +##### Retrieve Plugin Associated to a Specific Consumer + +
    /consumers/{consumer username or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`consumer username or id`
    **required** | The unique identifier **or** the username of the Consumer to retrieve. +`plugin id`
    **required** | The unique identifier of the Plugin to retrieve. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.plugin_json }} +``` + + +--- + +### Update Plugin + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Plugin + +
    /plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`plugin id`
    **required** | The unique identifier of the Plugin to update. + + +##### Update Plugin Associated to a Specific Route + +
    /routes/{route name or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`route name or id`
    **required** | The unique identifier **or** the name of the Route to update. +`plugin id`
    **required** | The unique identifier of the Plugin to update. + + +##### Update Plugin Associated to a Specific Service + +
    /services/{service name or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to update. +`plugin id`
    **required** | The unique identifier of the Plugin to update. + + +##### Update Plugin Associated to a Specific Consumer + +
    /consumers/{consumer username or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`consumer username or id`
    **required** | The unique identifier **or** the username of the Consumer to update. +`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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Plugin + +
    /plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`plugin id`
    **required** | The unique identifier of the Plugin to create or update. + + +##### Create Or Update Plugin Associated to a Specific Route + +
    /routes/{route name or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`route name or id`
    **required** | The unique identifier **or** the name of the Route to create or update. +`plugin id`
    **required** | The unique identifier of the Plugin to create or update. + + +##### Create Or Update Plugin Associated to a Specific Service + +
    /services/{service name or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to create or update. +`plugin id`
    **required** | The unique identifier of the Plugin to create or update. + + +##### Create Or Update Plugin Associated to a Specific Consumer + +
    /consumers/{consumer username or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`consumer username or id`
    **required** | The unique identifier **or** the username of the Consumer to create or update. +`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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Plugin + +
    /plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`plugin id`
    **required** | The unique identifier of the Plugin to delete. + + +##### Delete Plugin Associated to a Specific Route + +
    /routes/{route name or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`route name or id`
    **required** | The unique identifier **or** the name of the Route to delete. +`plugin id`
    **required** | The unique identifier of the Plugin to delete. + + +##### Delete Plugin Associated to a Specific Service + +
    /services/{service name or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`service name or id`
    **required** | The unique identifier **or** the name of the Service to delete. +`plugin id`
    **required** | The unique identifier of the Plugin to delete. + + +##### Delete Plugin Associated to a Specific Consumer + +
    /consumers/{consumer username or id}/plugins/{plugin id}
    + +{:.indent} +Attributes | Description +---:| --- +`consumer username or id`
    **required** | The unique identifier **or** the username of the Consumer to delete. +`plugin id`
    **required** | The unique identifier of the Plugin to delete. + + +#### Response + +``` +HTTP 204 No Content +``` + + +--- + +### Retrieve Enabled Plugins +{:.badge .dbless} + +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" + ] +} +``` + + +--- + +## Certificate Object + +A certificate object represents a public certificate, and can be optionally paired with the +corresponding private key. These objects are used by Kong to handle SSL/TLS termination for +encrypted requests, or for use as a trusted CA store when validating peer certificate of +client/service. Certificates are optionally associated with SNI objects to +tie a cert/key pair to one or more hostnames. + +If intermediate certificates are required in addition to the main +certificate, they should be concatenated together into one string according to +the following order: main certificate on the top, followed by any intermediates. + +Certificates can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.certificate_json }} +``` + +### Add Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Certificate + +
    /certificates
    + + +#### Request Body + +{{ page.certificate_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.certificate_json }} +``` + + +--- + +### List Certificates +{:.badge .dbless} + +##### 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 +{:.badge .dbless} + +##### Retrieve Certificate + +
    /certificates/{certificate id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to retrieve. + + +##### Retrieve Certificate Associated to a Specific Upstream + +
    /upstreams/{upstream name or id}/client_certificate
    + +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream associated to the Certificate to be retrieved. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.certificate_json }} +``` + + +--- + +### Update Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update Certificate + +
    /certificates/{certificate id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to update. + + +##### Update Certificate Associated to a Specific Upstream + +
    /upstreams/{upstream name or id}/client_certificate
    + +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream associated to the Certificate to be updated. + + +#### Request Body + +{{ page.certificate_body }} + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.certificate_json }} +``` + + +--- + +### Update Or Create Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update Certificate + +
    /certificates/{certificate id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to create or update. + + +##### Create Or Update Certificate Associated to a Specific Upstream + +
    /upstreams/{upstream name or id}/client_certificate
    + +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream associated to the Certificate to be created or updated. + + +#### 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete Certificate + +
    /certificates/{certificate id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to delete. + + +##### Delete Certificate Associated to a Specific Upstream + +
    /upstreams/{upstream name or id}/client_certificate
    + +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream associated to the Certificate to be deleted. + + +#### Response + +``` +HTTP 204 No Content +``` + + +--- + +## CA Certificate Object + +A CA certificate object represents a trusted CA. These objects are used by Kong to +verify the validity of a client or server certificate. + +CA Certificates can be both [tagged and filtered by tags](#tags). + + +```json +{{ page.ca_certificate_json }} +``` + +### Add CA Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create CA Certificate + +
    /ca_certificates
    + + +#### Request Body + +{{ page.ca_certificate_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.ca_certificate_json }} +``` + + +--- + +### List CA Certificates +{:.badge .dbless} + +##### List All CA Certificates + +
    /ca_certificates
    + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.ca_certificate_data }} + "next": "http://localhost:8001/ca_certificates?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve CA Certificate +{:.badge .dbless} + +##### Retrieve CA Certificate + +
    /ca_certificates/{ca_certificate id}
    + +{:.indent} +Attributes | Description +---:| --- +`ca_certificate id`
    **required** | The unique identifier of the CA Certificate to retrieve. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.ca_certificate_json }} +``` + + +--- + +### Update CA Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update CA Certificate + +
    /ca_certificates/{ca_certificate id}
    + +{:.indent} +Attributes | Description +---:| --- +`ca_certificate id`
    **required** | The unique identifier of the CA Certificate to update. + + +#### Request Body + +{{ page.ca_certificate_body }} + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.ca_certificate_json }} +``` + + +--- + +### Update Or Create CA Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update CA Certificate + +
    /ca_certificates/{ca_certificate id}
    + +{:.indent} +Attributes | Description +---:| --- +`ca_certificate id`
    **required** | The unique identifier of the CA Certificate to create or update. + + +#### Request Body + +{{ page.ca_certificate_body }} + + +Inserts (or replaces) the CA Certificate under the requested resource with the +definition specified in the body. The CA Certificate will be identified via the `name +or id` attribute. + +When the `name or id` attribute has the structure of a UUID, the CA Certificate being +inserted/replaced will be identified by its `id`. Otherwise it will be +identified by its `name`. + +When creating a new CA 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 CA Certificate + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete CA Certificate + +
    /ca_certificates/{ca_certificate id}
    + +{:.indent} +Attributes | Description +---:| --- +`ca_certificate id`
    **required** | The unique identifier of the CA 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create SNI + +
    /snis
    + + +##### Create SNI Associated to a Specific Certificate + +
    /certificates/{certificate name or id}/snis
    + +{:.indent} +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 +{:.badge .dbless} + +##### List All SNIs + +
    /snis
    + + +##### List SNIs Associated to a Specific Certificate + +
    /certificates/{certificate name or id}/snis
    + +{:.indent} +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 +{:.badge .dbless} + +##### Retrieve SNI + +
    /snis/{sni name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`sni name or id`
    **required** | The unique identifier **or** the name of the SNI to retrieve. + + +##### Retrieve SNI Associated to a Specific Certificate + +
    /certificates/{certificate id}/snis/{sni name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to retrieve. +`sni 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Update SNI + +
    /snis/{sni name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`sni name or id`
    **required** | The unique identifier **or** the name of the SNI to update. + + +##### Update SNI Associated to a Specific Certificate + +
    /certificates/{certificate id}/snis/{sni name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to update. +`sni 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Or Update SNI + +
    /snis/{sni name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`sni name or id`
    **required** | The unique identifier **or** the name of the SNI to create or update. + + +##### Create Or Update SNI Associated to a Specific Certificate + +
    /certificates/{certificate id}/snis/{sni name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to create or update. +`sni 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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Delete SNI + +
    /snis/{sni name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`sni name or id`
    **required** | The unique identifier **or** the name of the SNI to delete. + + +##### Delete SNI Associated to a Specific Certificate + +
    /certificates/{certificate id}/snis/{sni name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to delete. +`sni 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 load balance +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 + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +##### Create Upstream + +
    /upstreams
    + + +##### Create Upstream Associated to a Specific Certificate + +
    /certificates/{certificate name or id}/upstreams
    + +{:.indent} +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 Upstream. + + +#### Request Body + +{{ page.upstream_body }} + + +#### Response + +``` +HTTP 201 Created +``` + +```json +{{ page.upstream_json }} +``` + + +--- + +### List Upstreams +{:.badge .dbless} + +##### List All Upstreams + +
    /upstreams
    + + +##### List Upstreams Associated to a Specific Certificate + +
    /certificates/{certificate name or id}/upstreams
    + +{:.indent} +Attributes | Description +---:| --- +`certificate name or id`
    **required** | The unique identifier or the `name` attribute of the Certificate whose Upstreams are to be retrieved. When using this endpoint, only Upstreams associated to the specified Certificate will be listed. + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ +{{ page.upstream_data }} + "next": "http://localhost:8001/upstreams?offset=6378122c-a0a1-438d-a5c6-efabae9fb969" +} +``` + + +--- + +### Retrieve Upstream +{:.badge .dbless} + +#### Retrieve Upstream + +
    /upstreams/{upstream name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream to retrieve. + + +#### Retrieve Upstream Associated to a Specific Certificate + +
    /certificates/{certificate id}/upstreams/{upstream name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to retrieve. +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream to retrieve. + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.upstream_json }} +``` + +--- + +### Update Upstream + +{:.note} +> **Note**: This API is not available in DB-less mode. + +
    /upstreams/{upstream name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream to update. + +#### Update Upstream Associated to a Specific Certificate + +
    /certificates/{certificate id}/upstreams/{upstream name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to update. +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream to update. + +#### Request Body + +{{ page.upstream_body }} + + +#### Response + +``` +HTTP 200 OK +``` + +```json +{{ page.upstream_json }} +``` + +--- + +### Update Or Create Upstream + +{:.note} +> **Note**: This API is not available in DB-less mode. + + +
    /upstreams/{upstream name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`upstream 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 Certificate + +
    /certificates/{certificate id}/upstreams/{upstream name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to create or update. +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream to create or update. + +#### 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 + +{:.note} +> **Note**: This API is not available in DB-less mode. + +
    /upstreams/{upstream name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream to delete. + +#### Delete Upstream Associated to a Specific Certificate + +
    /certificates/{certificate id}/upstreams/{upstream name or id}
    + +{:.indent} +Attributes | Description +---:| --- +`certificate id`
    **required** | The unique identifier of the Certificate to delete. +`upstream name or id`
    **required** | The unique identifier **or** the name of the Upstream to delete. + +#### Response + +``` +HTTP 204 No Content +``` + + +--- + +### Show Upstream Health for Node +{:.badge .dbless} + +Displays the health status for all Targets of a given Upstream, or for +the whole 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 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 execution. +* 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. + +When the request query parameter `balancer_health` is set to `1`, the +`data` field of the response refers to the Upstream itself, and its `health` +attribute is defined by the state of all of Upstream's Targets, according +to the field `healthchecks.threshold`. + + +
    /upstreams/{name or id}/health/
    + +{:.indent} +Attributes | Description +---:| --- +`name or id`
    **required** | The unique identifier **or** the name of the Upstream for which to display Target health. + + +#### Request Querystring Parameters + +Attributes | Description +---:| --- +`balancer_health`
    *optional* | If set to 1, Kong will return the health status of the Upstream itself. See the `healthchecks.threshold` property. + + +#### 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 + } + ] +} +``` + +If `balancer_health=1`: +``` +HTTP 200 OK +``` + +```json +{ + "data": { + "health": "HEALTHY", + "id": "07131005-ba30-4204-a29f-0927d53257b4" + }, + "next": null, + "node_id": "cbb297c0-14a9-46bc-ad91-1d0ef9b42df9" +} +``` + + +--- + +## 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, modified, or deleted. Changes take effect on the fly. + +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 + +{:.note} +> **Note**: This API is not available in DB-less mode. + +#### Create Target Associated to a Specific Upstream + +
    /upstreams/{upstream_id}/targets
    + +{:.indent} +Attributes | Description +---:| --- +`upstream_id`
    **required** | The unique identifier 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 +{:.badge .dbless} + +#### List Targets Associated to a Specific Upstream + +
    /upstreams/{upstream_id}/targets
    + +{:.indent} +Attributes | Description +---:| --- +`upstream_id`
    **required** | The unique identifier 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" +} +``` + + +--- + +### Update Target + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +Update a target. + + +
    /upstreams/{upstream name or id}/targets/{host:port or id}
    + +{:.indent} +Attributes | Description +---:| --- +`upstream name or id`
    **required** | The unique identifier **or** the name of the upstream for which to update the target. +`host:port or id`
    **required** | The host:port combination element of the target to update, or the `id` of an existing target entry. + + +#### Response + +``` +HTTP 201 Created +``` + + +--- + +### Delete Target + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +Remove a target from the load balancer. + + +
    /upstreams/{upstream name or id}/targets/{host:port or id}
    + +{:.indent} +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 Address As Healthy + +{:.note} +> **Note**: This API is not available in DB-less mode. + +Set the current health status of an individual address resolved by a target +in the load balancer to "healthy" in the entire Kong cluster. + +This endpoint can be used to manually re-enable an address resolved by 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 address 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}/{address}/healthy
    + +{:.indent} +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. +`address`
    **required** | The host/port combination element of the address to set as healthy. + + +#### Response + +``` +HTTP 204 No Content +``` + + +--- + +### Set Target Address As Unhealthy + + + +{:.note} +> **Note**: This API is not available in DB-less mode. + +Set the current health status of an individual address resolved by a target +in the load balancer to "unhealthy" in the entire Kong cluster. + +This endpoint can be used to manually disable an address and have it stop +responding to requests. Upstreams only forward requests to healthy nodes, so +this call tells Kong to start skipping this address. + +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 +addresses. Note that if active health checks are enabled and the probe detects +that the address is actually healthy, it will automatically re-enable it again. +To permanently remove a target from the balancer, you should [delete a +target](#delete-target) instead. + + +
    /upstreams/{upstream name or id}/targets/{target or id}/unhealthy
    + +{:.indent} +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 +``` + + +--- + +### Set Target As Healthy +{:.badge .dbless} + +Set the current health status of a target in the load balancer to "healthy" +in the entire Kong cluster. This sets the "healthy" status to all addresses +resolved by this target. + +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
    + +{:.indent} +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 +{:.badge .dbless} + +Set the current health status of a target in the load balancer to "unhealthy" +in the entire Kong cluster. This sets the "unhealthy" status to all addresses +resolved by this target. + +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. + +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 balancer, you should [delete a +target](#delete-target) instead. + + +
    /upstreams/{upstream name or id}/targets/{target or id}/unhealthy
    + +{:.indent} +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 +{:.badge .dbless} + +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/
    + +{:.indent} +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]: /gateway/{{page.release}}/reference/clustering +[cli]: /gateway/{{page.release}}/reference/cli +[active]: /gateway/{{page.release}}/reference/health-checks-circuit-breakers/#active-health-checks +[healthchecks]: /gateway/{{page.release}}/reference/health-checks-circuit-breakers +[secure-admin-api]: /gateway/{{page.release}}/admin-api/secure-admin-api +[proxy-reference]: /gateway/{{page.release}}/reference/proxy diff --git a/app/gateway/2.7.x/admin-api/licenses/examples.md b/app/gateway/2.7.x/admin-api/licenses/examples.md new file mode 100644 index 000000000000..3a5afb455cce --- /dev/null +++ b/app/gateway/2.7.x/admin-api/licenses/examples.md @@ -0,0 +1,201 @@ +--- +title: Licenses Examples +badge: enterprise +--- + +{:.note} +> **Note:** The `/licenses` endpoint does not override standard +license configuration. + +The `/licenses` endpoint provides a way to configure your {{site.base_gateway}} +without using environment variables or placing a plaintext file +in your system directories. In a hybrid mode deployment, the Admin API +`/licenses` endpoint also configures all data planes in the cluster, simplifying +the configuration process. + +## Prerequisites +Remove all standard license configurations from traditional deployments, control +planes, and data planes. + +If you deploy a license using environmental variables or a plaintext +file, this configuration takes precedence over the +`/licenses` endpoint and **does not** communicate any changes to the Admin API. +If you try to use the `/licenses` endpoint while having a license configured +in some other way, the new license will not apply. + +## List all licenses + +Submit the following request: + +```bash +http GET :8001/licenses +``` + +{% navtabs codeblock %} +{% navtab Response when license exists %} +```json +{ + "data": [ + { + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "updated_at": 1500508800 + }, + ], + "next": null, +} +``` +{% endnavtab %} +{% navtab Response if there is no license %} + +```json +{ + "data": [], + "next": null +} +``` +{% endnavtab %} +{% endnavtabs %} + +## List a license + +Using the ID of the license, submit the following request: + +```bash +http GET :8001/licenses/30b4edb7-0847-4f65-af90-efbed8b0161f +``` + +```json +{ + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +## Add a license + +### Auto-generated ID + +To generate an ID automatically, submit a `POST` request directly to `/licenses`: + +```bash +http POST :8001/licenses \ + payload='{"license":{"payload":{"admin_seats":"1","customer":"Example Company, Inc","dataplanes":"1","license_creation_date":"2017-07-20","license_expiration_date":"2017-07-20","license_key":"00141000017ODj3AAG_a1V41000004wT0OEAU","product_subscription":"Konnect Enterprise","support_plan":"None"},"signature":"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b","version":"1"}}' +``` + +Response: +```json +{ + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +### Manually provided ID + +To create a license with a custom ID, submit a `PUT` request to +`/licenses/`: + +```bash +http PUT :8001/licenses/e8201120-4ee3-43ca-9e92-3fed08b1a15d \ + payload='{"license":{"payload":{"admin_seats":"1","customer":"Example Company, Inc","dataplanes":"1","license_creation_date":"2017-07-20","license_expiration_date":"2017-07-20","license_key":"00141000017ODj3AAG_a1V41000004wT0OEAU","product_subscription":"Konnect Enterprise","support_plan":"None"},"signature":"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b","version":"1"}}' +``` + +Response: +```json +{ + "created_at": 1500508800, + "id": "e8201120-4ee3-43ca-9e92-3fed08b1a15d", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +**Note**: If the provided ID exists, the request will perform + an update to the license for the given ID instead of creating a new + `license` entity. + +## Update a license + +To update a license, submit a `PATCH` request to an existing license ID: + +```bash +http PATCH :8001/licenses/30b4edb7-0847-4f65-af90-efbed8b0161f \ + payload='{"license":{"payload":{"admin_seats":"1","customer":"Example Company, Inc","dataplanes":"1","license_creation_date":"2017-07-20","license_expiration_date":"2017-07-21","license_key":"00141000017ODj3AAG_a1V41000004wT0OEAU","product_subscription":"Konnect Enterprise","support_plan":"None"},"signature":"24cc21223633044c15c300be19cacc26ccc5aca0dd9a12df8a7324a1970fe304bc07b8dcd7fb08d7b92e04169313377ae3b550ead653b951bc44cd2eb59f6beb","version":"1"}}' +``` + +Response: +```json +{ + "created_at": 1500595200, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-21\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"24cc21223633044c15c300be19cacc26ccc5aca0dd9a12df8a7324a1970fe304bc07b8dcd7fb08d7b92e04169313377ae3b550ead653b951bc44cd2eb59f6beb\",\"version\":\"1\"}}", + "updated_at": 1500595200 +} +``` + +## Generate license report + +To generate a report, submit a `GET` request directly to `/license/report`: + +```bash +http GET :8001/license/report +``` + +{% navtabs codeblock %} +{% navtab Response when license exists %} +```json +{ + "counters": [ + { + "bucket": "2021-12", + "request_count": 0 + } + ], + "db_version": "postgres 9.6.19", + "kong_version": "2.7.0.0", + "license_key": "ASDASDASDASDASDASDASDASDASD_ASDASDA", + "rbac_users": 0, + "services_count": 0, + "system_info": { + "cores": 4, + "hostname": "13b867agsa008", + "uname": "Linux x86_64" + }, + "workspaces_count": 1 +} +``` +{% endnavtab %} +{% navtab Response if there is no license %} + +```json +{ + "counters": [ + { + "bucket": "2021-12", + "request_count": 0 + } + ], + "db_version": "postgres 9.6.19", + "kong_version": "2.7.0.0", + "license_key": "UNLICENSED", + "rbac_users": 0, + "services_count": 0, + "system_info": { + "cores": 4, + "hostname": "13b867agsa008", + "uname": "Linux x86_64" + }, + "workspaces_count": 1 +} +``` +{% endnavtab %} +{% endnavtabs %} + + +[services]: /gateway/{{page.release}}/admin-api/#service-object diff --git a/app/gateway/2.7.x/admin-api/licenses/reference.md b/app/gateway/2.7.x/admin-api/licenses/reference.md new file mode 100644 index 000000000000..f400230a7657 --- /dev/null +++ b/app/gateway/2.7.x/admin-api/licenses/reference.md @@ -0,0 +1,277 @@ +--- +title: Licenses Reference +badge: enterprise + +licenses_attribute_id: | + Attributes | Description + ---:| --- + `id` | The **license's** unique ID. + +licenses_body: | + Attribute | Description + ---:| --- + `payload` | The **Enterprise license** in JSON format. +--- + +The {{site.base_gateway}} Licenses feature is configurable through the +[Admin API]. This feature lets you configure a license in your +{{site.base_gateway}} cluster, in both traditional and hybrid mode deployments. +In hybrid mode deployments, the control plane sends licenses configured +through the `/licenses` endpoint to all data planes in the cluster. The data +planes use the most recent `updated_at` license. + +## List licenses +**Endpoint** + +
    /licenses/
    + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "updated_at": 1500508800 + }, + ], + "next": null, +} +``` + +If there are no licenses stored by {{site.base_gateway}}, the data array will +be empty. + +```json +{ + "data": [], + "next": null +} +``` + +## List a specific license + +**Endpoint** + +
    /licenses/{id}
    + +{{ page.licenses_attribute_id }} + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-21\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"24cc21223633044c15c300be19cacc26ccc5aca0dd9a12df8a7324a1970fe304bc07b8dcd7fb08d7b92e04169313377ae3b550ead653b951bc44cd2eb59f6beb\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +## Add a license + +To create a license using an auto-generated UUID: + +**Endpoint** + +
    /licenses/
    + +**Request Body** + +{{ page.licenses_body }} + +When using `POST`, if the request payload **does** +contain a valid {{site.base_gateway}} license, the license will be added. + +If the request payload **does not** contain a valid licence, a `400 BAD REQUEST` +will be returned. + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "created_at": 1500508800, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +## Update or add a license + +**Endpoint** + +
    /licenses/{id}
    + +{{ page.licenses_attribute_id }} + +When using `PUT`, if the request payload +**does not** contain an entity's primary key (`id` for licenses), the +license will be added and assigned the given ID. + +If the request payload +**does** contain an entity's primary key (`id` for Licenses), the license +will be replaced with the given payload attribute. +If the ID is not a valid UUID, a `400 BAD REQUEST` will be returned. If the ID +is omitted, a `405 NOT ALLOWED` will be returned. + +**Request Body** + +{{ page.licenses_body }} + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1500508800, + "id": "e8201120-4ee3-43ca-9e92-3fed08b1a15d", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-20\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b\",\"version\":\"1\"}}", + "updated_at": 1500508800 +} +``` + +## Update a license + +**Endpoint** + +
    /licenses/{id}
    + +{{ page.licenses_attribute_id }} + +When using `PATCH`, if the request payload +**does** contain an entity's primary key (`id` for licenses), the license will +be replaced with the given payload attribute. + +If the request payload **does +not** contain an entity's primary key (`id` for licenses), a `404 NOT FOUND` +will be returned or if the request payload contains a invalid licence, a `400 +BAD REQUEST` will be returned. + +**Request Body** + +{{ page.licenses_body }} + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1500595200, + "id": "30b4edb7-0847-4f65-af90-efbed8b0161f", + "payload": "{\"license\":{\"payload\":{\"admin_seats\":\"1\",\"customer\":\"Example Company, Inc\",\"dataplanes\":\"1\",\"license_creation_date\":\"2017-07-20\",\"license_expiration_date\":\"2017-07-21\",\"license_key\":\"00141000017ODj3AAG_a1V41000004wT0OEAU\",\"product_subscription\":\"Konnect Enterprise\",\"support_plan\":\"None\"},\"signature\":\"24cc21223633044c15c300be19cacc26ccc5aca0dd9a12df8a7324a1970fe304bc07b8dcd7fb08d7b92e04169313377ae3b550ead653b951bc44cd2eb59f6beb\",\"version\":\"1\"}}", + "updated_at": 1500595200 +} +``` + +## Delete a license + +**Endpoint** + +
    /licenses/{id}
    + +{{ page.licenses_attribute_id }} + +**Response** + +``` +HTTP 204 No Content +``` + +## Generate a report + +Generate a report on the {{site.base_gateway}} instance to gather monthly usage data. + +
    /license/report
    + +Fields available in the report: + +Field | Description +------|------------ +`counters` | Counts the number of requests made in a given month.

    • `bucket`: Year and month when the requests were processed. If the value in `bucket` is `UNKNOWN`, then the requests were processed before {{site.base_gateway}} 2.7.0.1.
    • `request_count`: Number of requests processed in the given month and year. +`db_version` | The type and version of the datastore {{site.base_gateway}} is using. +`kong_version` | The version of the {{site.base_gateway}} instance. +`license_key` | An encrypted identifier for the current license key. If no license is present, the field displays as `UNLICENSED`. +`rbac_users` | The number of users registered with through RBAC. +`services_count` | The number of configured services in the {{site.base_gateway}} instance. +`system_info` | Displays information about the system running {{site.base_gateway}}.

    • `cores`: Number of CPU cores on the node
    • `hostname`: Encrypted system hostname
    • `uname`: Operating system +`workspaces_count` | The number of workspaces configured in the {{site.base_gateway}} instance. + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "counters": [ + { + "bucket": "2021-12", + "request_count": 0 + } + ], + "db_version": "postgres 9.6.19", + "kong_version": "2.7.0.0", + "license_key": "ASDASDASDASDASDASDASDASDASD_ASDASDA", + "rbac_users": 0, + "services_count": 0, + "system_info": { + "cores": 4, + "hostname": "13b867agsa008", + "uname": "Linux x86_64" + }, + "workspaces_count": 1 +} +``` + +If there are no licenses stored by {{site.base_gateway}}, the report will include +`"license_key": "UNLICENSED"`: + +``` +HTTP 200 OK +``` + +```json +{ + "counters": [ + { + "bucket": "2021-12", + "request_count": 0 + } + ], + "db_version": "postgres 9.6.19", + "kong_version": "2.7.0.0", + "license_key": "UNLICENSED", + "rbac_users": 0, + "services_count": 0, + "system_info": { + "cores": 4, + "hostname": "13b867agsa008", + "uname": "Linux x86_64" + }, + "workspaces_count": 1 +} +``` + +[Admin API]: /gateway/{{page.release}}/admin-api/ diff --git a/app/gateway/2.7.x/admin-api/rbac/examples.md b/app/gateway/2.7.x/admin-api/rbac/examples.md new file mode 100644 index 000000000000..6194a41da917 --- /dev/null +++ b/app/gateway/2.7.x/admin-api/rbac/examples.md @@ -0,0 +1,1046 @@ +--- +title: RBAC Examples +badge: enterprise +--- + +This chapter aims to provide a step-by-step tutorial on how to set up +RBAC and see it in action, with an end-to-end use case. The chosen +use case demonstrates how **RBAC with workspaces** can be coupled +to achieve a flexible organization of teams and users in complex +hierarchies. Make sure to read the [RBAC Overview][rbac-overview] page +and to glance over the [RBAC Admin API][rbac-admin] chapter, keeping it +open as a reference. + +## Use Case + +For the sake of example, let's say a given company has a {{site.base_gateway}} +cluster to be shared with 3 teams: teamA, teamB, and teamC. While the Kong +cluster are shared among these teams, they want to be able to segment +their entities in such a way that management of entities in one team doesn't +disrupt operation in some other team. As shown in the +[Workspaces Examples Page][workspaces-examples], such a use case is possible +with workspaces. On top of workspaces, though, each team wants to enforce +access control over their Workspace, which is possible with RBAC. **To sum up, +Workspaces and RBAC are complementary: Workspaces provide segmentation of +Admin API entities, while RBAC provides access control**. + +## Bootstrapping the first RBAC user—the Super Admin + +**Note:** It is possible to create the first Super Admin at the time +of migration as described in the [Getting Started Guide][getting-started-guide]. +If you chose this option, skip to [Enforcing RBAC](#enforcing-rbac). + +Before anything, we will assume the Kong Admin—or, more interestingly, +the KongOps Engineer—in charge of operating Kong, will create a Super Admin +user, before actually enforcing RBAC and restarting Kong with RBAC enabled. + +As Kong ships with a handy set of default RBAC Roles—the `super-admin`, +the `admin`, and `read-only`—the task of creating a Super Admin user is +quite easy: + +Create the RBAC user, named `super-admin`: + +``` +http :8001/rbac/users name=super-admin +{ + "user_token": "M8J5A88xKXa7FNKsMbgLMjkm6zI2anOY", + "id": "da80838d-49f8-40f6-b673-6fff3e2c305b", + "enabled": true, + "created_at": 1531009435000, + "name": "super-admin" +} +``` + +As the `super-admin` user name coincides with an existing `super-admin` +role, it gets automatically added to the `super-admin` role—which can be +confirmed with the following command: + +``` +http :8001/rbac/users/super-admin/roles +{ + "roles": [ + { + "comment": "Full access to all endpoints, across all workspaces", + "created_at": 1531009724000, + "name": "super-admin", + "id": "b924ac91-e83f-4136-a5a4-4a7ff92594a8" + } + ], + "user": { + "created_at": 1531009858000, + "id": "e6897cc0-0c34-4a9c-9f0b-cc65b4f04d68", + "name": "super-admin", + "enabled": true, + "user_token": "vajeOlkybsn0q0VD9qw9B3nHYOErgY7b8" + } +} + +``` + +## Enforcing RBAC + +As the `super-admin` user has just been created, the Kong Admin may now +restart Kong with RBAC enforced, with, e.g.: + +``` +KONG_ENFORCE_RBAC=on kong restart +``` + +**NOTE**: This is one of the possible ways of enforcing RBAC and restarting +Kong; another possibility is editing the Kong configuration file and +restarting. + +Before we move on, note that we will be using the Super Admin user, but we +could, in fact, be moving without RBAC enabled, and having our Kong Admin do +all the job of setting up the RBAC hierarchy. We want, however, to stress the +fact that RBAC is powerful enough to allow a flexible separation of tasks. To +summarize: + +- **Kong Admin**: this user has physical access to Kong infrastructure; her +task is to bootstrap the Kong cluster as well as its configuration, including +initial RBAC users; +- **RBAC Super Admin**: created by the Kong Admin, has the role of managing +RBAC users, roles, etc; this could all be done by the **Kong Admin**, but let's +give him a break. + +## Super Admin creates the teams Workspaces + +The Super Admin will now set up our 3 teams: teamA, teamB, and teamC, creating +one workspace for each, one admin for each. Enough talking. + +Creating workspaces for each team—this overlaps a bit with +[Workspaces Examples][workspaces-examples], yes, but it will make our +exploration of RBAC + Workspaces easier: + +**Team A**: + +``` +http :8001/workspaces name=teamA Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "name": "teamA", + "created_at": 1531014100000, + "id": "1412f3a6-4d9b-4b9d-964e-60d8d63a9d46" +} + +``` + +**Team B**: + +``` +http :8001/workspaces name=teamB Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "name": "teamB", + "created_at": 1531014143000, + "id": "7dee8c56-c6db-4125-b87a-b508baa33c66" +} +``` + +**Team C**: + +``` +http :8001/workspaces name=teamC Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "name": "teamC", + "created_at": 1531014171000, + "id": "542c8662-17cc-49eb-af50-6eb14f3b2e8a" +} +``` + +**NOTE**: this is the RBAC Super Admin creating workspaces—note his +token being passed in through the `Kong-Admin-Token` HTTP header. + +## Super Admin Creates one Admin for each Team + +**Team A**: + +``` +http :8001/teamA/rbac/users name=adminA Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "user_token": "qv1VLIpl8kHj7lC1QOKwRdCMXanqEDii", + "id": "4d315ff9-8c1a-4844-9ea2-21b16204a154", + "enabled": true, + "created_at": 1531015165000, + "name": "adminA" +} +``` + +**Team B**: + +``` +http :8001/teamB/rbac/users name=adminB Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "user_token": "IX5vHVgYqM40tLcctdmzRtHyfxB4ToYv", + "id": "49641fc0-8c9d-4507-bc7a-2acac8f2903a", + "enabled": true, + "created_at": 1531015221000, + "name": "adminB" +} +``` + +**Team C**: + +``` +http :8001/teamC/rbac/users name=adminC Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "user_token": "w2f7tsuUW4BerXocZIMRQHE84nK2ZAo7", + "id": "74643f69-8852-49f9-b363-21971bac4f52", + "enabled": true, + "created_at": 1531015304000, + "name": "teamC" +} +``` + +With this, all of the teams have one admin and each admin can only be seen +in his corresponding workspace. To verify: + +``` +http :8001/teamA/rbac/users Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "created_at": 1531014784000, + "id": "1faaacd1-709f-4762-8c3e-79f268ec8faf", + "name": "adminA", + "enabled": true, + "user_token": "n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG" + } + ] +} +``` + +Similarly, workspaces teamB and teamC only show their respective admins: + +``` +http :8001/teamB/rbac/users Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "created_at": 1531014805000, + "id": "3a829408-c1ee-4764-8222-2d280a5de441", + "name": "adminB", + "enabled": true, + "user_token": "C8b6kTTN10JFyU63ORjmCQwVbvK4maeq" + } + ] +} +``` + +``` +http :8001/teamC/rbac/users Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "created_at": 1531014813000, + "id": "84d43cdb-5274-4b74-ad22-615e50f005e3", + "name": "adminC", + "enabled": true, + "user_token": "zN5Nj8U1MiGR7vVQKvl8odaGBDI6mjgY" + } + ] +} +``` + +## Super Admin Creates Admin Roles for Teams + +Super Admin is now done creating RBAC Admin users for each team; his next +task is to create admin roles that will effectively grant permissions to admin +users. + +The admin role must have access to all of the Admin API, restricted to his +workspace. + +Setting up the Admin role—pay close attention to the request parameters: + +``` +http :8001/teamA/rbac/roles/ name=admin Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "created_at": 1531016728000, + "id": "d40e61ab-8dad-4ef2-a48b-d11379f7b8d1", + "name": "admin" +} +``` + +Creating role endpoint permissions: + +``` +http :8001/teamA/rbac/roles/admin/endpoints/ endpoint=* workspace=teamA actions=* Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "total": 1, + "data": [ + { + "endpoint": "*", + "created_at": 1531017322000, + "role_id": "d40e61ab-8dad-4ef2-a48b-d11379f7b8d1", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": false, + "workspace": "teamA" + } + ] +} +``` + +Next logical step is to add the adminA user—admin of Team A—to the Admin +role in his workspace: + +``` +http :8001/teamA/rbac/users/adminA/roles/ roles=admin Kong-Admin-Token:vajeOlkbsn0q0VD9qw9B3nHYOErgY7b8 +{ + "roles": [ + { + "comment": "Default user role generated for adminA", + "created_at": 1531014784000, + "id": "e2941b41-92a4-4f49-be89-f1a452bdecd0", + "name": "adminA" + }, + { + "created_at": 1531016728000, + "id": "d40e61ab-8dad-4ef2-a48b-d11379f7b8d1", + "name": "admin" + } + ], + "user": { + "created_at": 1531014784000, + "id": "1faaacd1-709f-4762-8c3e-79f268ec8faf", + "name": "adminA", + "enabled": true, + "user_token": "n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG" + } +} +``` + +Note the admin role in the list above. + +With these steps, Team A's admin user is now able to manage his team. To +validate that, let's try to list RBAC users in Team B using Team A's admin +user token—and see that we are not allowed to do so: + +``` +http :8001/teamB/rbac/users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "message": "Invalid RBAC credentials" +} +``` + +Said admin is, however, allowed to list RBAC users in Team A's workspace: + +``` +http :8001/teamA/rbac/users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "total": 1, + "data": [ + { + "created_at": 1531014784000, + "id": "1faaacd1-709f-4762-8c3e-79f268ec8faf", + "name": "adminA", + "enabled": true, + "user_token": "n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG" + } + ] +} +``` + +If the same procedure is repeated for Team B and Team C, they will end up with +a similar set up, with an admin role and an admin user, both restricted to the +team's workspace. + +And so Super Admin ends his participation; individual team admins are now able +to set up his teams users and entities! + +## Team Admins Create Team Regular Users + +From this point on, team admins are able to drive the process; the next logical +step is for Team users to be created; such team users could be, for example, +engineers that are part of Team A (or B or C). Let's go ahead and do that, +using Admin A's user token. + +Before regular users can be created, a role needs to be available for them. +Such a role needs to have permissions to all of Admin API endpoints, except +RBAC and Workspaces—regular users will not need access to these in general +and, if they do, the Admin can grant them. + +**Creating the regular users role**: + +``` +http :8001/teamA/rbac/roles/ name=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531020346000, + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "name": "users" +} +``` + +**Creating permissions in the regular users role**: + +First, permission to all of Admin API—positive permission on \*: + +``` +http :8001/teamA/rbac/roles/users/endpoints/ endpoint=* workspace=teamA actions=* Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "endpoint": "*", + "created_at": 1531020573000, + "role_id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": false, + "workspace": "teamA" +} +``` + +Then, filter out RBAC and workspaces with negative permissions: + +``` +http :8001/teamA/rbac/roles/users/endpoints/ endpoint=/rbac/* workspace=teamA actions=* Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "endpoint": "/rbac/*", + "created_at": 1531020744000, + "role_id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": true, + "workspace": "teamA" +} +``` + +``` +http :8001/teamA/rbac/roles/users/endpoints/ endpoint=/workspaces/* workspace=teamA actions=* Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "endpoint": "/workspaces/*", + "created_at": 1531020778000, + "role_id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": true, + "workspace": "teamA" +} +``` + +**IMPORTANT**: as explained in the [Wildcards in Permissions](#wildcards-in-permissions) +section, the meaning of `*` is not the expected generic globbing one might +be used to. As such, `/rbac/*` or `/workspaces/*` do not match all of the +RBAC and Workspaces endpoints. For example, to cover all of the RBAC API, +one would have to define permissions for the following endpoints: + +- `/rbac/*` +- `/rbac/*/*` +- `/rbac/*/*/*` +- `/rbac/*/*/*/*` +- `/rbac/*/*/*/*/*` + +Team A just got 3 new members: foogineer, bargineer, and bazgineer. Admin A +will welcome them to the team by creating RBAC users for them and giving them +access to Kong! + +Create foogineer: + +``` +http :8001/teamA/rbac/users name=foogineer Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531019797000, + "id": "0b4111da-2827-4767-8651-a327f7a559e9", + "name": "foogineer", + "enabled": true, + "user_token": "dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI" +} +``` + +Add foogineer to the `users` role: + +``` +http :8001/teamA/rbac/users/foogineer/roles roles=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for foogineer", + "created_at": 1531019797000, + "id": "125c4212-b882-432d-a323-9cbe38b1d0df", + "name": "foogineer" + }, + { + "created_at": 1531020346000, + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "name": "users" + } + ], + "user": { + "created_at": 1531019797000, + "id": "0b4111da-2827-4767-8651-a327f7a559e9", + "name": "foogineer", + "enabled": true, + "user_token": "dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI" + } +} +``` + +Create bargineer: + +``` +http :8001/teamA/rbac/users name=bargineer Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531019837000, + "id": "25dfa68e-32e8-48d8-815f-6fedfd2fb4a6", + "name": "bargineer", + "enabled": true, + "user_token": "eZj3WUc46wO3zEJbLP3Y4VGvNaUgGlyv" +} +``` + +Add bargineer to the `users` role: + +``` +http :8001/teamA/rbac/users/bargineer/roles roles=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for bargineer", + "created_at": 1531019837000, + "id": "3edb00c2-9ae1-423d-ac81-bec702c29e37", + "name": "bargineer" + }, + { + "created_at": 1531020346000, + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b", + "name": "users" + } + ], + "user": { + "created_at": 1531019837000, + "id": "25dfa68e-32e8-48d8-815f-6fedfd2fb4a6", + "name": "bargineer", + "enabled": true, + "user_token": "eZj3WUc46wO3zEJbLP3Y4VGvNaUgGlyv" + } +} +``` + +Create bazgineer: + +``` +http :8001/teamA/rbac/users name=bazgineer Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531019937000, + "id": "ea7207d7-0d69-427b-b288-ce696b7f4690", + "name": "bazgineer", + "enabled": true, + "user_token": "r8NhaT213Zm8o1woQF4ZyQyCVjFRgGp3" +} +``` + +Add bazgineer to the `users` role: + +``` +http :8001/teamA/rbac/users/bazgineer/roles roles=users Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for bazgineer", + "created_at": 1531019937000, + "id": "fa409bb6-c86c-45d2-8a6b-ac8e71de2cc9", + "name": "bazgineer" + }, + { + "created_at": 1531020346000, + "name": "users", + "id": "9846b92c-6820-4741-ac31-425b3d6abc5b" + } + ], + "user": { + "created_at": 1531019937000, + "id": "ea7207d7-0d69-427b-b288-ce696b7f4690", + "name": "bazgineer", + "enabled": true, + "user_token": "r8NhaT213Zm8o1woQF4ZyQyCVjFRgGp3" + } +} +``` + +## Regular Team Users use their tokens + +foogineer, bargineer, and bazgineer all have gotten their RBAC user tokens +from their Team A admin, and are now allowed to explore Kong—within the +confines of their Team A workspace. Let's validate they can in fact do anything +they wish, except over RBAC and Workspaces. + +Try listing Workspaces: + +``` +http :8001/teamA/workspaces/ Kong-Admin-Token:dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI +{ + "message": "foogineer, you do not have permissions to read this resource" +} +``` + +Enable some plugin—e.g., key-auth: + +``` +http :8001/teamA/plugins name=key-auth Kong-Admin-Token:dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI +{ + "created_at": 1531021732000, + "config": { + "key_in_body": false, + "run_on_preflight": true, + "anonymous": "", + "hide_credentials": false, + "key_names": [ + "apikey" + ] + }, + "id": "cdc85ef0-804b-4f92-aafd-3ff58512e445", + "enabled": true, + "name": "key-auth" +} +``` + +List currently enabled plugins: + +``` +http :8001/teamA/plugins Kong-Admin-Token:dNeYvYAwvjOJdoReVJZXF8vLBXQioKkI +{ + "total": 1, + "data": [ + { + "created_at": 1531021732000, + "config": { + "key_in_body": false, + "run_on_preflight": true, + "anonymous": "", + "hide_credentials": false, + "key_names": [ + "apikey" + ] + }, + "id": "cdc85ef0-804b-4f92-aafd-3ff58512e445", + "name": "key-auth", + "enabled": true + } + ] +} +``` + +This ends our use case tutorial; it demonstrates the power of RBAC and +workspaces with a real-world scenario. Following, we will approach **Entity-Level +RBAC**, an extension of our powerful access control to entity-level granularity. + +## Entity-Level RBAC: a Primer + +{{site.base_gateway}}'s new RBAC implementation goes one step further in permissions +granularity: in addition to "endpoint" permissions, it supports entity-level +permissions, meaning that particular entities, identified by their unique ID, +can be allowed or disallowed access in a role. + +Refreshing our minds, RBAC is [enforced](#enforcing-rbac) with the `enforce_rbac` +configuration directive—or with its `KONG_ENFORCE_RBAC` environment variable +counterpart. Such directive is an enum, with 4 possible values: + +- `on`: similarly to the previous RBAC implementation, applies Endpoint-level +access control +- `entity`: applies **only** Entity-level access control +- `both`: applies **both Endpoint and Entity level access control** +- `off`: disables RBAC enforcement + +If one sets it to either `entity` or `both`, Kong will enforce entity-level +access control. However, as with endpoint-level access control, permissions +must be bootstrapped before enforcement is enabled. + +### Creating Entity-Level Permissions + +Team A just got one new, temporary, team member: qux. Admin A, the admin of +Team A, has already created his qux RBAC user; he needs, however, to limit +access that qux has over entities in Team A workspace, giving him read access +to only a couple of entities—say, a Service and a Route. For that, he will +use Entity-Level RBAC. + +**Admin A creates a role for the temporary user qux**: + +``` +http :8001/teamA/rbac/roles name=qux-role Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "name": "qux-role", + "created_at": 1531065975000, + "id": "ffe93269-7993-4308-965e-0286d0bc87b9" +} +``` + +We will assume the following entities exist: + +A service: + +``` +http :8001/teamA/services Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "next": null, + "data": [ + { + "host": "httpbin.konghq.com", + "created_at": 1531066074, + "connect_timeout": 60000, + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43", + "protocol": "http", + "name": "service1", + "read_timeout": 60000, + "port": 80, + "path": null, + "updated_at": 1531066074, + "retries": 5, + "write_timeout": 60000 + } + ] +} +``` + +and a Route to that Service: + +``` +http :8001/teamA/routes Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "next": null, + "data": [ + { + "created_at": 1531066253, + "id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b", + "hosts": null, + "updated_at": 1531066253, + "preserve_host": false, + "regex_priority": 0, + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "paths": [ + "/anything" + ], + "methods": null, + "strip_path": false, + "protocols": [ + "http", + "https" + ] + } + ] +} +``` + +**Admin A creates entity permissions in qux-role**: + +Add service1—whose ID is 3ed24101-19a7-4a0b-a10f-2f47bcd4ff43: + +``` +http :8001/teamA/rbac/roles/qux-role/entities entity_id=3ed24101-19a7-4a0b-a10f-2f47bcd4ff43 actions=read Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531066684000, + "role_id": "ffe93269-7993-4308-965e-0286d0bc87b9", + "entity_id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43", + "negative": false, + "entity_type": "services", + "actions": [ + "read" + ] +} +``` + +Add the route—whose ID is d25afc46-dc59-48b2-b04f-d3ebe19f6d4b: + +``` +http :8001/teamA/rbac/roles/qux-role/entities entity_id=d25afc46-dc59-48b2-b04f-d3ebe19f6d4b actions=read Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "created_at": 1531066728000, + "role_id": "ffe93269-7993-4308-965e-0286d0bc87b9", + "entity_id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b", + "negative": false, + "entity_type": "routes", + "actions": [ + "read" + ] +} +``` + +**Admin A adds qux to his role**: + +``` +http :8001/teamA/rbac/users/qux/roles roles=qux-role Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "roles": [ + { + "comment": "Default user role generated for qux", + "created_at": 1531065373000, + "name": "qux", + "id": "31614171-4174-42b4-9fae-43c9ce14830f" + }, + { + "created_at": 1531065975000, + "name": "qux-role", + "id": "ffe93269-7993-4308-965e-0286d0bc87b9" + } + ], + "user": { + "created_at": 1531065373000, + "id": "4d87bf78-5824-4756-b0d0-ceaa9bd9b2d5", + "name": "qux", + "enabled": true, + "user_token": "sUnv6uBehM91amYRNWESsgX3HzqoBnR5" + } +} +``` + +Checking permissions appear listed: + +``` +http :8001/teamA/rbac/users/qux/permissions Kong-Admin-Token:n5bhjgv0speXp4N7rSUzUj8PGnl3F5eG +{ + "entities": { + "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b": { + "actions": [ + "read" + ], + "negative": false + }, + "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43": { + "actions": [ + "read" + ], + "negative": false + } + }, + "endpoints": {} +} +``` + +That is, 2 entities permissions and no endpoint permissions. + +Admin A is done setting up qux, and qux can now use his user token to read +his two entities over Kong's admin API. + +We will assume that Admin A [enabled entity-level enforcement](#enforcing-rbac). +Note that as qux has **no endpoint-level permissions**, if both endpoint and +entity-level enforcement is enabled, he will not be able to read his entities - +endpoint-level validation comes before entity-level. + +**qux tries listing all RBAC users** + +``` +http :8001/teamA/rbac/users/ Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "message": "qux, you do not have permissions to read this resource" +} +``` + +**qux tries listing all Workspaces** + +``` +http :8001/teamA/rbac/workspaces/ Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "message": "qux, you do not have permissions to read this resource" +} +``` + +**qux tries to access service1** + +``` +http :8001/teamA/services/service1 Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "host": "httpbin.konghq.com", + "created_at": 1531066074, + "connect_timeout": 60000, + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43", + "protocol": "http", + "name": "service1", + "read_timeout": 60000, + "port": 80, + "path": null, + "updated_at": 1531066074, + "retries": 5, + "write_timeout": 60000 +} +``` + +Similarly, he can access his Route: + +``` +http :8001/teamA/routes/3ed24101-19a7-4a0b-a10f-2f47bcd4ff43 Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "created_at": 1531066253, + "strip_path": false, + "hosts": null, + "preserve_host": false, + "regex_priority": 0, + "updated_at": 1531066253, + "paths": [ + "/anything" + ], + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "methods": null, + "protocols": [ + "http", + "https" + ], + "id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b" +} +``` + +## Closing Remarks + +We will end this chapter with a few closing remarks. + +### Wildcards in Permissions + +RBAC supports the use of wildcards—represented by the `*` character—in many +aspects of permissions: + +**Creating endpoint permissions—`/rbac/roles/:role/endpoints`** + +To create an endpoint permission, one must pass the parameters below, all of +which can be replaced by a * character: + +- `endpoint`: `*` matches **any endpoint** +- `workspace`: `*` matches **any workspace** +- `actions`: `*` evaluates to **all actions—read, update, create, delete** + +**Special case**: `endpoint`, in addition to a single `*`, also accepts `*` +within the endpoint itself, replacing a URL segment between `/`; for example, +all of the following are valid endpoints: + +- `/rbac/*`: where `*` replaces any possible segment—e.g., `/rbac/users`, +`/rbac/roles`, etc +- `/services/*/plugins`: `*` matches any Service name or ID + +Note, however, that `*` **is not** a generic, shell-like, glob pattern. + +If `workspace` is omitted, it defaults to the current request's workspace. For +example, a role-endpoint permission created with `/teamA/roles/admin/endpoints` +is scoped to workspace `teamA`. + +**Creating entity permissions—`/rbac/roles/:role/entities`** + +Similarly, for entity permissions, the following parameters accept a `*` +character: + +- `entity_id`: `*` matches **any entity ID** + +### Entities Concealing in Entity-Level RBAC + +With Entity-Level RBAC enabled, endpoints that list all entities of a +particular collection will only list entities that the user has access to; +in the example above, if user qux listed all Routes, he would only get as +response the entities he has access to—even though there could be more: + +``` +http :8001/teamA/routes Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "next": null, + "data": [ + { + "created_at": 1531066253, + "id": "d25afc46-dc59-48b2-b04f-d3ebe19f6d4b", + "hosts": null, + "updated_at": 1531066253, + "preserve_host": false, + "regex_priority": 0, + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "paths": [ + "/anything" + ], + "methods": null, + "strip_path": false, + "protocols": [ + "http", + "https" + ] + } + ] +} +``` + +Some Kong endpoints carry a `total` field in responses; with Entity-Level RBAC +enabled, the global count of entities is displayed, but only entities the user +has access to are themselves shown; for example, if Team A has a number of +plugins configured, but qux only has access to one of them, the following +would be the expected output for a GET request to `/teamA/plugins`: + +``` +http :8001/teamA/plugins Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "total": 2, + "data": [ + { + "created_at": 1531070344000, + "config": { + "key_in_body": false, + "run_on_preflight": true, + "anonymous": "", + "hide_credentials": false, + "key_names": [ + "apikey" + ] + }, + "id": "8813dd0b-3e9d-4bcf-8a10-3112654f86e7", + "name": "key-auth", + "enabled": true + } + ] +} +``` + +Notice the `total` field is 2, but qux only got one entity in the response. + +### Creating Entities in Entity-Level RBAC + +As entity-level RBAC provides access control to individual existing entities, +it does not apply to creation of new entities; for that, endpoint-level +permissions must be configured and enforced. For example, if endpoint-level +permissions are not enforced, qux will be able to create new entities: + +``` +http :8001/teamA/routes paths[]=/anything service.id=3ed24101-19a7-4a0b-a10f-2f47bcd4ff43 strip_path=false Kong-Admin-Token:sUnv6uBehM91amYRNWESsgX3HzqoBnR5 +{ + "created_at": 1531070828, + "strip_path": false, + "hosts": null, + "preserve_host": false, + "regex_priority": 0, + "updated_at": 1531070828, + "paths": [ + "/anything" + ], + "service": { + "id": "3ed24101-19a7-4a0b-a10f-2f47bcd4ff43" + }, + "methods": null, + "protocols": [ + "http", + "https" + ], + "id": "6ee76f74-3c96-46a9-ae48-72df0717d244" +} +``` + +and qux will automatically have permissions to perform any actions to entities +he created. + +--- + +[rbac-overview]: /gateway/{{page.release}}/configure/auth/rbac +[rbac-admin]: /gateway/{{page.release}}/admin-api/rbac/reference +[workspaces-examples]: /gateway/{{page.release}}/admin-api/workspaces/examples +[getting-started-guide]: /gateway/{{page.release}}/get-started/comprehensive diff --git a/app/gateway/2.7.x/admin-api/rbac/reference.md b/app/gateway/2.7.x/admin-api/rbac/reference.md new file mode 100644 index 000000000000..fa59644e1757 --- /dev/null +++ b/app/gateway/2.7.x/admin-api/rbac/reference.md @@ -0,0 +1,950 @@ +--- +title: RBAC Reference +badge: enterprise +--- + +Kong {{site.base_gateway}}'s RBAC feature is configurable through Kong's +[Admin API](/gateway/{{page.release}}/admin-api/) or via the [Kong Manager](/gateway/{{page.release}}/configure/auth/rbac/). + +There are 4 basic entities involving RBAC. + +- **User**: The entity interacting with the system. Can be associated with + zero, one or more roles. Example: user `bob` has token `1234`. +- **Role**: Set of permissions (`role_endpoint` and + `role_entity`). Has a name and can be associated with zero, one or + more permissions. Example: user bob is associated with role + `developer`. +- **role_endpoint**: A set of enabled or disabled (see `negative` + parameter) actions (`read`, `create`, `update`, `delete`) + `endpoint`. Example: Role `developer` has 1 role_endpoint: `read & + write` to endpoint `/routes` +- **role_entity**: A set of enabled or disabled (see `negative` + parameter) actions (`read`, `create`, `update`, `delete`) + `entity`. Example: Role `developer` has 1 role_entity: `read & write + & delete` to entity `283fccff-2d4f-49a9-8730-dc8b71ec2245`. + +## Add a User +**Endpoint** + +
    /rbac/users
    + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `name` | The RBAC user name. | +| `user_token` | The authentication token to be presented to the Admin API. The value will be hashed and cannot be fetched in plaintext. | +| `enabled`
    optional | A flag to enable or disable the user. By default, users are enabled. | +| `comment`
    optional | A string describing the RBAC user object. | + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "comment": null, + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "doc_knight", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" +} +``` +___ + +## Retrieve a User +**Endpoint** + +
    /rbac/users/{name_or_id}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC user name or UUID. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "doc_lord", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" +} +``` +___ + +## List Users +**Endpoint** + +
    /rbac/users/
    + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "comment": null, + "created_at": 1557512629, + "enabled": true, + "id": "f035f120-a95e-4327-b2ae-8fa264601d75", + "name": "doc_lord", + "user_token": "$2b$09$TIMneYcTosdG9WbzRsqcweAS2zote8g6I8HqXAtbFHR1pds2ymsh6", + "user_token_ident": "88ea3" + }, + { + "comment": null, + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "doc_knight", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" + } + ], + "next": null +} +``` + +⚠️ **Note**: **RBAC Users** associated with **Admins** will _not_ be +listed with **`GET`** `/rbac/users`. Instead, use +[**`GET`** `/admins`](/gateway/{{page.release}}/admin-api/admins/reference/#list-admins) +to list all **Admins**. + +___ + +## Update a User +**Endpoint** + +
    /rbac/users/{name_or_id}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC user name or UUID. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `user_token`
    optional | The authentication token to be presented to the Admin API. If this value is not present, the token will automatically be generated. | +| `enabled`
    optional | A flag to enable or disable the user. By default, users are enabled. | +| `comment`
    optional | A string describing the RBAC user object. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "this comment came from a patch request", + "created_at": 1557522650, + "enabled": true, + "id": "fa6881b2-f49f-4007-9475-577cd21d34f4", + "name": "donut_lord", + "user_token": "$2b$09$Za30VKAAAmyoB9zF2PNEF.9hgKcN2BdKkptPMCubPK/Ps08lzZjYG", + "user_token_ident": "4d870" +} +``` +___ + +## Delete a User +**Endpoint** + +
    /rbac/users/{name_or_id}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC user name or UUID. | + +**Response** + +``` +HTTP 204 No Content +``` +___ + +## Add a Role +**Endpoint** + +
    /rbac/roles
    + +| Attribute | Description | +| --------- | ----------- | +| `name` | The RBAC role name. | +| `comment`
    optional | A string describing the RBAC user object. | + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "comment": null, + "created_at": 1557532241, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "service_reader" +} +``` +___ + +## Retrieve a Role +Endpoint + +
    /rbac/roles/{name_or_id}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "created_at": 1557532241, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "service_reader" +} +``` +___ + +## List Roles +**Endpoint** + +
    /rbac/roles
    + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "comment": "Full access to all endpoints, across all workspaces—except RBAC Admin API", + "created_at": 1557506249, + "id": "38a03d47-faae-4366-b430-f6c10aee5029", + "name": "admin" + }, + { + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1557506249, + "id": "4141675c-8beb-41a5-aa04-6258ab2d2f7f", + "name": "read-only" + }, + { + "comment": "Full access to all endpoints, across all workspaces", + "created_at": 1557506249, + "id": "888117e0-f2b3-404d-823b-dee595423505", + "name": "super-admin" + }, + { + "comment": null, + "created_at": 1557532241, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "name": "doc_lord" + } + ], + "next": null +} +``` +___ + +## Update or Create a Role +**Endpoint** + +
    /rbac/roles/{name_or_id}
    + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `name` | The RBAC role name. | +| `comment`
    optional | A string describing the RBAC user object. | + +The behavior of `PUT` endpoints is the following: if the request +payload **does** contain an entity's primary key, the payload will +"replace" the entity specified by the given primary key. If the +primary key is **not** that of an existing entity, the entity will be +created with the given payload. + +**Response** + +If creating the entity: + +``` +HTTP 201 Created +``` + +If replacing the entity: + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "the best", + "created_at": 1557532566, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "doc_lord" +} +``` + +## Update a Role +**Endpoint** + +
    /rbac/roles/{name_or_id}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role or UUID. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `comment`
    optional | A string describing the RBAC role object. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "comment from patch request", + "created_at": 1557532566, + "id": "b5c5cfd4-3330-4796-9b7b-6026e91e3ad6", + "is_default": false, + "name": "service_reader" +} +``` +___ + +## Delete a Role +**Endpoint** + +
    /rbac/roles/{name_or_id}
    + +| Attribute | Description | +| --------- | ----------- | +| `name` | The RBAC role name. | + +**Response** + +``` +HTTP 204 No Content +``` +___ + +## Add a Role Endpoint Permission +**Endpoint** + +
    /rbac/roles/{name_or_id}/endpoints
    + + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name. | + + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `workspace` | Workspace tied to the endpoint. Defaults to the default permission. Special value of "*" means **all** workspaces are affected | +| `endpoint` | Endpoint associated with this permission. | +| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this endpoint. By default this value is false. | +| `actions` | One or more actions associated with this permission. This is a comma separated string (read,create,update,delete) | +| `comment`
    optional | A string describing the RBAC permission object. | + +`endpoint` must be the path of the associated endpoint. They can be +exact matches, or contain wildcards, represented by `*`. + +- Exact matches; for example: + * /services/ + * /services/foo + +- Wildcards; for example: + * /services/* + * /services/*/plugins + +Where `*` replaces exactly one segment between slashes (or the end of +the path). + +Note that wildcards can be nested (`/rbac/*`, `/rbac/*/*`, +`/rbac/*/*/*` would refer to all paths under `/rbac/`) + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764505, + "endpoint": "/consumers", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" +} +``` + +--- + +## Retrieve a Role Endpoint Permission +**Endpoint** + +
    /rbac/roles/{name_or_id}/endpoints/{workspace_name_or_id}/{endpoint}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `workspace_name_or_id` | The workspace name or UUID. | +| `endpoint` | The endpoint associated with this permission. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764505, + "endpoint": "/consumers", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" +} +``` + +--- + + + +## List Role Endpoints Permissions +**Endpoint** + +
    /rbac/roles/{role_name_or_id}/endpoints
    + +| Attribute | Description | +| --------- | ----------- | +| `role_name_or_id` | The RBAC role name or UUID. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764505, + "endpoint": "/consumers", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" + }, + { + "actions": [ + "read" + ], + "created_at": 1557764438, + "endpoint": "/services", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" + } + ] +} +``` + +--- + +## Update a Role Endpoint Permission +**Endpoint** + +
    /rbac/roles/{name_or_id}/endpoints/{workspace_name_or_id}/{endpoint}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `workspace_name_or_id` | The workspace name or UUID. | +| `endpoint` | The endpoint associated with this permission. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. | +| `actions` | One or more actions associated with this permission. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "actions": [ + "delete", + "create", + "update", + "read" + ], + "created_at": 1557764438, + "endpoint": "/services", + "negative": false, + "role": { + "id": "23df9f20-e7cc-4da4-bc89-d3a08f976e50" + }, + "workspace": "default" +} +``` + +--- + + + +## Delete a Role Endpoint Permission +**Endpoint** + +
    /rbac/roles/{name_or_id}/endpoints/{workspace_name_or_id}/{endpoint}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `workspace_name_or_id` | The workspace name or UUID. | +| `endpoint` | The endpoint associated with this permission. | + +**Response** + +``` +HTTP 204 No Content +``` + +--- + + + +## Add a Role Entity Permission +**Endpoint** +
    /rbac/roles/{name_or_id}/entities
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. | +| `entity_id` | id of the entity associated with this permission. +| `entity_type` | Type of the entity of a given `entity_id`. | +| `actions` | One or more actions associated with this permission. | +| `comment`
    optional | A string describing the RBAC permission object | + +`entity_id` must be the ID of an entity in Kong; if the ID of a +workspace is given, the permission will apply to all entities in that +workspace. Future entities belonging to that workspace will get the +same permissions. A wildcard `*` will be interpreted as **all +entities** in the system. + + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "actions": [ + "delete", + "create", + "read" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } +} +``` + +--- + +## Retrieve a Role Entity Permission +**Endpoint** +
    /rbac/roles/{name_or_id}/entities/{entity_id}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC permission name or UUID. | +| `entity_id` | id of the entity associated with this permission. | + +**Response** + +``` +HTTP 200 Ok +``` + +```json +{ + "actions": [ + "delete", + "create", + "read" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } +} +``` + +--- + +## List Entity Permissions + +**Endpoint** +
    /rbac/roles/{name_or_id}/entities
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC permission name or UUID. | + +**Response** + +``` +HTTP 200 Ok +``` + +```json +{ + "data": [ + { + "actions": [ + "delete", + "create", + "read" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } + } + ] +} +``` + +--- +## Update an Entity Permission +**Endpoint** + +
    /rbac/roles/{name_or_id}/entities/{entity_id}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `entity_id` | The entity name or UUID. | + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `negative` | If true, explicitly disallow the actions associated with the permissions tied to this resource. By default this value is false. | +| `actions` | One or more actions associated with this permission. | + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "actions": [ + "update" + ], + "created_at": 1557771505, + "entity_id": "*", + "entity_type": "wildcard", + "negative": false, + "role": { + "id": "bba049fa-bf7e-40ef-8e89-553dda292e99" + } +} +``` + +--- + +## Delete an Entity Permission +**Endpoint** + +
    /rbac/roles/{name_or_id}/entities/{entity_id}
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | +| `entity_id` | The entity name or UUID. | + +**Response** + +``` +HTTP 204 No Content +``` + +--- + +## List Role Permissions +**Endpoint** +
    /rbac/roles/{name_or_id}/permissions/
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + + +**Response** + +``` +HTTP 200 OK +``` +```json +{ + "endpoints": { + "*": { + "*": { + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": false + }, + "/*/rbac/*": { + "actions": [ + "delete", + "create", + "update", + "read" + ], + "negative": true + } + } + }, + "entities": {} +} +``` + +## Add a User to a Role +**Endpoint** + +
    /rbac/users/{name_or_id}/roles
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `roles` | Comma-separated list of role names to assign to the user. | + +**Response** + +``` +HTTP 201 Created +``` +```json +{ + "roles": [ + { + "created_at": 1557772263, + "id": "aae80073-095f-4553-ba9a-bee5ed3b8b91", + "name": "doc-knight" + } + ], + "user": { + "comment": null, + "created_at": 1557772232, + "enabled": true, + "id": "b65ca712-7ceb-4114-87f4-5c310492582c", + "name": "gruce-wayne", + "user_token": "$2b$09$gZnMKK/mm/d2rAXN7gL63uL43mjdX/62iwMqdyCQwLyC0af3ce/1K", + "user_token_ident": "88ea3" + } +} +``` + +--- +## List a User's Roles +**Endpoint** + +
    /rbac/users/{name_or_id}/roles
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + + +**Response** + +``` +HTTP 200 OK +``` +```json + +{ + "roles": [ + { + "comment": "Read access to all endpoints, across all workspaces", + "created_at": 1557765500, + "id": "a1c810ee-8366-4654-ba0c-963ffb9ccf2e", + "name": "read-only" + }, + { + "created_at": 1557772263, + "id": "aae80073-095f-4553-ba9a-bee5ed3b8b91", + "name": "doc-knight" + } + ], + "user": { + "comment": null, + "created_at": 1557772232, + "enabled": true, + "id": "b65ca712-7ceb-4114-87f4-5c310492582c", + "name": "gruce-wayne", + "user_token": "$2b$09$gZnMKK/mm/d2rAXN7gL63uL43mjdX/62iwMqdyCQwLyC0af3ce/1K", + "user_token_ident": "88ea3" + } +} +``` + +--- +## Delete a Role from a User +**Endpoint** + +
    /rbac/users/{name_or_id}/roles
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + + +**Request Body** + +| Attribute | Description | +| --------- | ----------- | +| `roles` | Comma-separated list of role names to assign to the user. | + +**Response** + +``` +HTTP 204 No Content +``` + +--- + +## List a User's Permissions +**Endpoint** + +
    /rbac/users/{name_or_id}/permissions
    + +| Attribute | Description | +| --------- | ----------- | +| `name_or_id` | The RBAC role name or UUID. | + +**Response** + +``` +HTTP 200 OK +``` +```json +{ + "endpoints": { + "*": { + "*": { + "actions": [ + "read" + ], + "negative": false + } + } + }, + "entities": {} +} + +``` diff --git a/app/gateway/2.7.x/admin-api/secure-admin-api.md b/app/gateway/2.7.x/admin-api/secure-admin-api.md new file mode 100644 index 000000000000..c40d7db8f078 --- /dev/null +++ b/app/gateway/2.7.x/admin-api/secure-admin-api.md @@ -0,0 +1,245 @@ +--- +title: Securing the Admin API +--- + +{{site.base_gateway}}'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`. + +### 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. + +## 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, let's assume that Kong `admin_listen` is `127.0.0.1:8001`, so it is only +available from localhost. The port `8000` is serving proxy traffic, presumably exposed via +`myhost.dev:8000` + +We want to expose Admin API via the url `:8000/admin-api`, in a controlled way. We can do so by +creating a Service and Route for it from inside `127.0.0.1`: + +```bash +curl -X POST http://127.0.0.1:8001/services \ + --data name=admin-api \ + --data host=127.0.0.1 \ + --data port=8001 + +curl -X POST http://127.0.0.1:8001/services/admin-api/routes \ + --data paths[]=/admin-api +``` + +We can now transparently reach the Admin API through the proxy server, from outside `127.0.0.1`: + +```bash +curl myhost.dev:8000/admin-api/services +{ + "data":[ + { + "id": "653b21bd-4d81-4573-ba00-177cc0108dec", + "created_at": 1422386534, + "updated_at": 1422386534, + "name": "admin-api", + "retries": 5, + "protocol": "http", + "host": "127.0.0.1", + "port": 8001, + "path": "/admin-api", + "connect_timeout": 60000, + "write_timeout": 60000, + "read_timeout": 60000 + } + ], + "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. + +If you are using Docker to host {{site.ee_product_name}}, you can accomplish a similar task using a declarative configuration such as this one: + +``` yaml +_format_version: "1.1" + +services: +- name: admin-api + url: http://127.0.0.1:8001 + routes: + - paths: + - /admin-api + plugins: + - name: key-auth + +consumers: +- username: admin + keyauth_credentials: + - key: secret +``` + +Under this configuration, the Admin API will be available through the `/admin-api`, but only for requests accompanied with `?apikey=secret` query +parameters. + +Assuming that the file above is stored in `$(pwd)/kong.yml`, a DB-less {{site.ee_product_name}} can use it as it starts like this: + +``` bash +docker run -d --name kong-ee \ + -e "KONG_DATABASE=off" \ + -e "KONG_DECLARATIVE_CONFIG=/home/kong/kong.yml" + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + -v $(pwd):/home/kong + kong-ee +``` + +With a PostgreSQL database, the initialization steps would be the following: + +``` bash +# Start PostgreSQL on a Docker container +# Notice that PG_PASSWORD needs to be set +docker run --name kong-ee-database \ + -p 5432:5432 \ + -e "POSTGRES_USER=kong" \ + -e "POSTGRES_DB=kong" \ + -e "POSTGRES_PASSWORD=$PG_PASSWORD" \ + -d postgres:9.6 + +# Run Kong migrations to initialize the database +docker run --rm \ + --link kong-ee-database:kong-ee-database \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=$PG_PASSWORD" \ + kong-ee kong migrations bootstrap + +# Load the configuration file which enables the Admin API loopback +# Notice that it is assumed that kong.yml is located in $(pwd)/kong.yml +docker run --rm \ + --link kong-ee-database:kong-ee-database \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=$PG_PASSWORD" \ + -v $(pwd):/home/kong \ + kong-ee kong config db_import /home/kong/kong.yml + +# Start Kong +docker run -d --name kong \ + --link kong-ee-database:kong-ee-database \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=$PG_PASSWORD" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + kong-ee +``` + +In both cases, once Kong is up and running, the Admin API would be available but protected: + +``` bash +curl myhost.dev:8000/admin-api/services +=> HTTP/1.1 401 Unauthorized + +curl myhost.dev:8000/admin-api/services?apikey=secret +=> HTTP/1.1 200 OK +{ + "data": [ + { + "ca_certificates": null, + "client_certificate": null, + "connect_timeout": 60000, + ... + } + ] +} +``` + +## 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]. + +## Role Based Access Control +{:.badge .enterprise} + +{{site.base_gateway}} users can configure [role-based access control](/gateway/{{page.release}}/configure/auth/rbac/) +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. + +[acl]: /hub/kong-inc/acl +[basic-auth]: /hub/kong-inc/basic-auth +[custom-configuration]: /gateway/{{page.release}}/reference/configuration/#custom-nginx-configuration +[ip-restriction]: /hub/kong-inc/ip-restriction +[key-auth]: /hub/kong-inc/key-auth diff --git a/app/gateway/2.7.x/admin-api/workspaces/examples.md b/app/gateway/2.7.x/admin-api/workspaces/examples.md new file mode 100644 index 000000000000..70878fc98d0d --- /dev/null +++ b/app/gateway/2.7.x/admin-api/workspaces/examples.md @@ -0,0 +1,188 @@ +--- +title: Workspace Examples +badge: enterprise +--- + +This chapter aims to provide a step-by-step tutorial on how to set up +workspaces, entities, and see it in action. + +## Important Note: Conflicting Services or Routes in workspaces + +Workspaces provide a way to segment Kong entities—entities in a workspace +are isolated from those in other workspaces. That said, entities +such as Services and Routes have "routing rules", which are pieces of info +attached to Services or Routes—such as HTTP method, URI, or host—that allow a +given proxy-side request to be routed to its corresponding upstream service. + +Admins configuring Services (or Routes) in their workspaces do not want traffic +directed to their Services or Routes to be swallowed by Services or Routes in other +workspaces; Kong allows them to prevent such undesired behavior—as long as +certain measures are taken. Below we outline the conflict detection algorithm +used by Kong to determine if a conflict occurs. + +* At Service or Route **creation or modification** time, Kong runs its internal +router: + - If no Services or Routes are found with matching routing rules, the creation + or modification proceeds + - If Services or Routes with matching routing rules are found **within the same + workspace**, proceed + - If Services or Routes are found **in a different workspace**: + * If the matching Service or Route **does not have an associated + `host` value**—`409 Conflict` + * If the matching Service or Route's `host` is a wildcard + - If they are the same, a conflict is reported—`409 Conflict` + - If they are not equal, proceed + * If the matching Service or Route's `host` is an absolute value, a + conflict is reported—`409 Conflict` + +## The Default workspace + +Kong creates a default workspace—unsurprisingly named `default`—whose goal +is to group all existing entities in Kong, where "existing entities" refers to: + +- Entities that were created in operation in previous versions & in case +one is migrating from an older Kong version; +- Entities that Kong creates at migration time—e.g., RBAC credentials, which +are provisioned at migration time as a convenience + +It will also hold entities that are created without being explicitly assigned to +a specific workspace. + +That said, it's worth noting that the default workspace is a workspace as any +other, the only difference being that it's created by Kong, at migration time. + +(Examples will be shown using the HTTPie command line client.) + +## Listing workspaces and its entities + +In a fresh {{site.base_gateway}} install, submit the +following request: + +``` +http GET :8001/workspaces +{ + "total": 1, + "data": [ + { + "created_at": 1529627841000, + "id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "name": "default" + } + ] +} +``` + +## Creating a workspace + +A more interesting example would be segmenting entities by teams; for the sake of +example, let's say they are teamA, teamB, and teamC. + +Each of these teams has its own set of entities—say, upstream services and +routes—and want to segregate their configurations and traffic; they can +achieve that with workspaces. + +``` +http POST :8001/workspaces name=teamA +{ + "created_at": 1528843468000, + "id": "735af96e-206f-43f7-88f0-b930d5fd4b7e", + "name": "teamA" +} +``` + +``` +http POST :8001/workspaces name=teamB +{ + "name": "teamB", + "created_at": 1529628574000, + "id": "a25728ac-6036-497c-82ee-524d4c22fcae" +} +``` + +``` +http POST :8001/workspaces name=teamC +{ + "name": "teamC", + "created_at": 1529628622000, + "id": "34b28f10-e1ec-4dad-9ac0-74780baee182" +} +``` + +At this point, if we list workspaces, we will get a total of 4—remember, +Kong provisions a "default" workspace and, on top of that, we created other +3. + +``` +{ + "data": [ + { + "created_at": 1529627841000, + "id": "a43fc3f9-98e4-43b0-b703-c3b1004980d5", + "name": "default" + }, + { + "created_at": 1529628818000, + "id": "5ed1c043-78cc-4fe2-924e-40b17ecd97bc", + "name": "teamA" + }, + { + "created_at": 1529628574000, + "id": "a25728ac-6036-497c-82ee-524d4c22fcae", + "name": "teamB" + }, + { + "created_at": 1529628622000, + "id": "34b28f10-e1ec-4dad-9ac0-74780baee182", + "name": "teamC" + } + ] + "total": 4, +} + +``` + +## Entities in different workspaces can have the same name! + +Different teams—belonging to different workspaces—are allowed to give any +name to their entities. To provide an example of that, let's say that Teams A, B, +and C want a particular consumer named `guest`—a different consumer for each +team, sharing the same username. + +``` +http :8001/teamA/consumers username=guest +{ + "created_at": 1529703386000, + "id": "2e230275-2a4a-41fd-b06b-bae37008aed2", + "type": 0, + "username": "guest" +} +``` + +``` +http :8001/teamB/consumers username=guest +{ + "created_at": 1529703390000, + "id": "8533e404-8d56-4481-a919-0ee35b8a768c", + "type": 0, + "username": "guest" +} +``` + +``` +http :8001/teamC/consumers username=guest +{ + "created_at": 1529703393000, + "id": "5fb180b0-0cd0-42e1-8d75-ce42a54b2909", + "type": 0, + "username": "guest" +} +``` + +With this, Teams A, B, and C will have the freedom to operate their `guest` +consumer independently, choosing authentication plugins or doing any other +operation that is allowed in the non-workspaced Kong world. + + +--- + +[services]: /gateway/{{page.release}}/admin-api/#service-object diff --git a/app/gateway/2.7.x/admin-api/workspaces/reference.md b/app/gateway/2.7.x/admin-api/workspaces/reference.md new file mode 100644 index 000000000000..7403198c7128 --- /dev/null +++ b/app/gateway/2.7.x/admin-api/workspaces/reference.md @@ -0,0 +1,352 @@ +--- +title: Workspaces Reference +badge: enterprise + +workspace_body: | + Attribute | Description + ---:| --- + `name` | The **Workspace** name. +--- + + +{{site.base_gateway}}'s Workspaces feature is configurable through Kong's +Admin API. + +## Workspace Object + +The **Workspace** object describes the **Workspace** entity, which has an ID +and a name. + +### Add Workspace + +**Endpoint** + +
    /workspaces/
    + +#### Request Body + +{{ page.workspace_body }} + +**Response** + +``` +HTTP 201 Created +``` + +```json +{ + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557441226, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "green-team" +} +``` + +### List Workspaces + +**Endpoint** + +
    /workspaces/
    + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "data": [ + { + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557419951, + "id": "00000000-0000-0000-0000-000000000000", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "default" + }, + { + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557441226, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "green-team" + } + ], + "next": null +} +``` + +### Update or Create a Workspace + +**Endpoint** + +
    /workspaces/{id}
    + +Attributes | Description +---:| --- +`id`
    **conditional** | The **Workspace's** unique ID, if replacing it.* + +* The behavior of `PUT` endpoints is the following: if the request payload **does +not** contain an entity's primary key (`id` for Workspaces), the entity will be +created with the given payload. If the request payload **does** contain an +entity's primary key, the payload will "replace" the entity specified by the +given primary key. If the primary key is **not** that of an existing entity, `404 +NOT FOUND` will be returned. + +#### Request Body + +Attribute | Description +---:| --- +`name` | The **Workspace** name. + +**Response** + +If creating the entity: + +``` +HTTP 201 Created +``` + +If replacing the entity: + +``` +HTTP 200 OK +``` + +```json +{ + "comment": null, + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557504202, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "rocket-team" +} +``` + +### Retrieve a Workspace + +**Endpoint** + +
    /workspaces/{name or id}
    + +Attributes | Description +---:| --- +`name or id`
    **required** | The unique identifier **or** the name of the **Workspace** to retrieve + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "config": { + "portal": false, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]" + }, + "created_at": 1557504202, + "id": "c663cca5-c6f6-474a-ae44-01f62aba16a9", + "meta": { }, + "name": "rocket-team" +} +``` + +### Retrieve Workspace Metadata + +#### Endpoint + +
    /workspaces/{name or id}/meta
    + +Attributes | Description +---:| --- +`name or id`
    **required** | The unique identifier **or** the name of the **Workspace** to retrieve + +#### Response + +``` +HTTP 200 OK +``` + +```json +{ + "counts": { + "acls": 1, + "basicauth_credentials": 1, + "consumers": 1234, + "files": 41, + "hmacauth_credentials": 1, + "jwt_secrets": 1, + "keyauth_credentials": 1, + "oauth2_authorization_codes": 1, + "oauth2_credentials": 1, + "oauth2_tokens": 1, + "plugins": 5, + "rbac_roles": 3, + "rbac_users": 12, + "routes": 15, + "services": 2, + "ssl_certificates": 1, + "ssl_servers_names": 1, + "targets": 1, + "upstreams": 1 + } +} +``` + +### Delete a Workspace + +**Endpoint** + +
    /workspaces/{name or id}
    + +Attributes | Description +---:| --- +`name or id`
    **required** | The unique identifier **or** the name of the **Workspace** to delete + +**Note:** All entities within a **Workspace** must be deleted before the +**Workspace** itself can be. + +**Response** + +``` +HTTP 204 No Content +``` + +### Update a Workspace + +**Endpoint** + +
    /workspaces/{name or id}
    + +Attributes | Description +---:| --- +`name or id`
    **required** | The unique identifier **or** the name of the **Workspace** to patch + +#### Request Body + +Attributes | Description +---:| --- +`comment` | A string describing the **Workspace** + +The behavior of `PATCH` endpoints prevents the renaming of a **Workspace**. + +**Response** + +``` +HTTP 200 OK +``` + +```json +{ + "comment": "this is a sample comment in the patch request", + "config": { + "meta": null, + "portal": false, + "portal_access_request_email": null, + "portal_approved_email": null, + "portal_auth": null, + "portal_auth_conf": null, + "portal_auto_approve": null, + "portal_cors_origins": null, + "portal_developer_meta_fields": "[{\"label\":\"Full Name\",\"title\":\"full_name\",\"validator\":{\"required\":true,\"type\":\"string\"}}]", + "portal_emails_from": null, + "portal_emails_reply_to": null, + "portal_invite_email": null, + "portal_reset_email": null, + "portal_reset_success_email": null, + "portal_token_exp": null + }, + "created_at": 1557509909, + "id": "c543d2c8-d297-4c9c-adf5-cd64212868fd", + "meta": { + "color": null, + "thumbnail": null + }, + "name": "green-team" +} +``` +--- + +[Admin API]: /gateway/{{page.release}}/admin-api/ diff --git a/app/gateway/2.7.x/compatibility.md b/app/gateway/2.7.x/compatibility.md new file mode 100644 index 000000000000..32ed9c832303 --- /dev/null +++ b/app/gateway/2.7.x/compatibility.md @@ -0,0 +1,37 @@ +--- +title: Kong Gateway Compatibility +--- + +Provided below are compatibility tables for {{site.base_gateway}}. Select a version +to see technologies that have been tested for interoperability with the Kong platform. + +Please see [{{site.base_gateway}} Version Support](/gateway/latest/support-policy/) +for more information about Kong's support for {{site.base_gateway}} and our +[Support & Maintenance Policy](https://konghq.com/supportandmaintenancepolicy). + +{% assign compat_data = site.data.tables.compat[page.release.value] %} + +{% unless compat_data %} +{% assign msg = "compat.json data is missing for Gateway " | append: page.release %} +{{ msg | raise_error }} +{% endunless %} + +

    If you need help using {{site.base_gateway}} with any of the supported technologies, ask a question in our community.

    + +

    If you have an Enterprise tier subscription, contact Kong Support.

    + +

    Supported operating systems

    +
      +{% for system in compat_data.os %} +
    • {{ system[0] | split: "-" | join: " " | capitalize }}: {{ system[1] }}
    • +{% endfor %} + +Kong only supports the latest vendor-supported minor version for RHEL and CentOS. +
    + +

    Supported databases

    +
      +{% for db in compat_data.databases %} +
    • {{ db[0] | capitalize }}: {{ db[1] }}
    • +{% endfor %} +
    diff --git a/app/gateway/2.7.x/configure/auth/allowing-multiple-authentication-methods.md b/app/gateway/2.7.x/configure/auth/allowing-multiple-authentication-methods.md new file mode 100644 index 000000000000..4ebd0109eb33 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/allowing-multiple-authentication-methods.md @@ -0,0 +1,108 @@ +--- +title: Allowing Multiple Authentication Methods +--- + +The default behavior for Kong authentication plugins is to require credentials +for all requests without regard for whether a request has been authenticated +via some other plugin. Configuring an anonymous consumer on your authentication +plugins allows you to offer clients multiple options for authentication. + +To begin, [create a Service](/gateway/{{page.release}}/admin-api/#service-object) and then create three consumers: + +```bash +curl -sX POST localhost:8001/consumers \ + -H "Content-Type: application/json" \ + --data '{"username": "anonymous"}' + +# {"created_at":1517528237000,"username":"anonymous","id":"d955c0cb-1a6e-4152-9440-414ebb8fee8a"} + +curl -sX POST localhost:8001/consumers \ + -H "Content-Type: application/json" \ + --data '{"username": "medvezhonok"}' + +# {"created_at":1517528259000,"username":"medvezhonok","id":"b3c95318-a932-4bb2-9d74-1298a3ffc87c"} + +curl -sX POST localhost:8001/consumers \ + -H "Content-Type: application/json" \ + --data '{"username": "ezhik"}' + +# {"created_at":1517528266000,"username":"ezhik","id":"47e74a17-dc08-4786-a8cf-d8e4f38a5459"} +``` + +The `anonymous` consumer does not correspond to any real user, and will only serve as a fallback. + +Next, we add both Key Auth and Basic Auth plugins to our consumer, and set the anonymous fallback to the consumer we created earlier. + +```bash +curl -sX POST localhost:8001/services/example-service/plugins/ \ + -H "Content-Type: application/json" \ + --data '{"name": "key-auth", "config": { "hide_credentials": true, "anonymous": "d955c0cb-1a6e-4152-9440-414ebb8fee8a"} }' + +# {"created_at":1517528304000,"config":{"key_in_body":false,"hide_credentials":true,"anonymous":"d955c0cb-1a6e-4152-9440-414ebb8fee8a","run_on_preflight":true,"key_names":["apikey"]},"id":"bb884f7b-4e48-4166-8c80-c858b5a4c357","name":"key-auth","service_id":"a2a168a8-4491-4fe1-9426-cde3b5fcd45b","enabled":true} + +curl -sX POST localhost:8001/services/example-service/plugins/ \ + -H "Content-Type: application/json" \ + --data '{"name": "basic-auth", "config": { "hide_credentials": true, "anonymous": "d955c0cb-1a6e-4152-9440-414ebb8fee8a"} }' + +# {"created_at":1517528499000,"config":{"hide_credentials":true,"anonymous":"d955c0cb-1a6e-4152-9440-414ebb8fee8a"},"id":"e5a40543-debe-4225-a879-a54901368e6d","name":"basic-auth","service_id":"a2a168a8-4491-4fe1-9426-cde3b5fcd45b","enabled":true} +``` + +If using [OpenID Connect](/hub/kong-inc/openid-connect/), you must also set `config.consumer_claim` along with `anonymous`, as setting `anonymous` alone will not map that consumer. + +At this point unauthenticated requests and requests with invalid credentials are still allowed. The anonymous consumer is allowed, and will be applied to any request that does not pass a set of credentials associated with some other consumer. + +```bash +curl -s localhost:8000/user-agent + +# {"user-agent": "curl/7.58.0"} + +curl -s localhost:8000/user-agent?apikey=nonsense + +# {"user-agent": "curl/7.58.0"} +``` + +We'll now add a Key Auth credential for one consumer, and a Basic Auth credential for another. + +```bash +curl -sX POST localhost:8001/consumers/medvezhonok/basic-auth \ + -H "Content-Type: application/json" \ + --data '{"username": "medvezhonok", "password": "hunter2"}' + +# {"created_at":1517528647000,"id":"bb350b87-f0d2-4605-b997-e28a116d8b6d","username":"medvezhonok","password":"f239a0404351d7170201e7f92fa9b3159e47bb01","consumer_id":"b3c95318-a932-4bb2-9d74-1298a3ffc87c"} + +curl -sX POST localhost:8001/consumers/ezhik/key-auth \ + -H "Content-Type: application/json" \ + --data '{"key": "hunter3"}' + +# {"id":"06412d6e-8d41-47f7-a911-3c821ec98f1b","created_at":1517528730000,"key":"hunter3","consumer_id":"47e74a17-dc08-4786-a8cf-d8e4f38a5459"} +``` + +Lastly, we add a Request Terminator to the anonymous consumer. + +```bash +curl -sX POST localhost:8001/consumers/d955c0cb-1a6e-4152-9440-414ebb8fee8a/plugins/ \ + -H "Content-Type: application/json" \ + --data '{"name": "request-termination", "config": { "status_code": 401, "content_type": "application/json; charset=utf-8", "body": "{\"error\": \"Authentication required\"}"} }' + +# {"created_at":1517528791000,"config":{"status_code":401,"content_type":"application\/json; charset=utf-8","body":"{\"error\": \"Authentication required\"}"},"id":"21fc5f6f-363f-4d79-b533-ce26d4478879","name":"request-termination","enabled":true,"consumer_id":"d955c0cb-1a6e-4152-9440-414ebb8fee8a"} +``` + +Requests with missing or invalid credentials are now rejected, whereas authorized requests using either authentication method are allowed. + +```bash +curl -s localhost:8000/user-agent?apikey=nonsense + +# {"error": "Authentication required"} + +curl -s localhost:8000/user-agent + +# {"error": "Authentication required"} + +curl -s localhost:8000/user-agent?apikey=hunter3 + +# {"user-agent": "curl/7.58.0"} + +curl -s localhost:8000/user-agent -u medvezhonok:hunter2 + +# {"user-agent": "curl/7.58.0"} +``` diff --git a/app/gateway/2.7.x/configure/auth/index.md b/app/gateway/2.7.x/configure/auth/index.md new file mode 100644 index 000000000000..65b96c918254 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/index.md @@ -0,0 +1,214 @@ +--- +title: Authentication Reference +--- + +Traffic to your Upstream services (APIs or microservices) is typically controlled by the application and +configuration of various Kong [authentication plugins][plugins]. Because 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 behavior. +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 `httpbin.konghq.com`, which will echo + the request: + + ```bash + $ curl -i -X POST \ + --url http://localhost:8001/services/ \ + --data 'name=example-service' \ + --data 'url=https://httpbin.konghq.com/anything' + ``` + + 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 use 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 httpbin 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 use 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 and so forth will require authentication by the other configured auth plugins. + +{:.important} +> When multiple authentication plugins are enabled in an `OR` fashion on a given service, +and you want anonymous access to be forbidden, then the [Request Termination plugin](/hub/kong-inc/request-termination/) +should be configured on the anonymous consumer. +Failure to do so will allow unauthorized requests. + + +[plugins]: /hub/ +[key-auth]: /hub/kong-inc/key-auth diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/basic.md b/app/gateway/2.7.x/configure/auth/kong-manager/basic.md new file mode 100644 index 000000000000..3a87f9154c71 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/basic.md @@ -0,0 +1,41 @@ +--- +title: Enable Basic Auth for Kong Manager +badge: enterprise +--- + +### Prerequisites + +To enable Basic Authentication, configure Kong with the following properties: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { "secret":"set-your-string-here" } +``` + +The **Sessions Plugin** requires a secret and is configured securely by default. + +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#session-security), and see [example configurations](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +## Step 1 + +Start Kong: + +``` +$ kong start [-c /path/to/kong/conf] +``` + +## Step 2 + +If you created a **Super Admin** via database migration, log in to Kong +Manager with the username `kong_admin` and the password +set in the environment variable. + +If you created a Super Admin via the Kong Manager "Organization" tab +as described in +[How to Create a Super Admin](/gateway/{{page.release}}/configure/auth/kong-manager/super-admin), +log in with the credentials you created after accepting the email +invitation. diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/email.md b/app/gateway/2.7.x/configure/auth/kong-manager/email.md new file mode 100644 index 000000000000..e58c6365480f --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/email.md @@ -0,0 +1,23 @@ +--- +title: Configuring Kong Manager to Send Email +badge: enterprise +--- + +A **Super Admin** can invite other **Admins** to register in Kong Manager, and **Admins** +can reset their passwords using "Forgot Password" functionality. Both of these +workflows use email to communicate with the user. + +Emails from Kong Manager require the following configuration: + +* [`admin_emails_from`](/gateway/{{page.release}}/reference/configuration/#admin_emails_from) +* [`admin_emails_reply_to`](/gateway/{{page.release}}/reference/configuration/#admin_emails_reply_to) +* [`admin_invitation_expiry`](/gateway/{{page.release}}/reference/configuration/#admin_invitation_expiry) + +Kong does not check for the validity of email +addresses set in the configuration. If the SMTP settings are +configured incorrectly, e.g., if they point to a non-existent +email address, Kong Manager will _not_ display an error message. + +For additional information about SMTP, refer to the +[general SMTP configuration](/gateway/{{page.release}}/reference/configuration/#general-smtp-configuration) +shared by Kong Manager and Dev Portal. diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/index.md b/app/gateway/2.7.x/configure/auth/kong-manager/index.md new file mode 100644 index 000000000000..cff317eb9886 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/index.md @@ -0,0 +1,66 @@ +--- +title: Securing Kong Manager +badge: enterprise +--- + +Kong Manager enables users with Admin accounts to access Kong entities such +as Services, Plugins, and Consumers. + +The following document summarizes Kong Manager's controls for *authentication* +and *authorization*. + +## Configuring Authentication + +{{site.base_gateway}} comes packaged with Authentication Plugins that can be used +to secure Kong Manager. Unlike enabling a Plugin on an entity or cluster, +enabling an Authentication Plugin for *only* Kong Manager requires turning +on `enforce_rbac`, setting `admin_gui_auth` to the desired type, proper +configuration of `admin_gui_session_conf`, and configuring `admin_gui_auth_conf` +if needed. + +Kong Manager currently supports the following Authentication Plugins: + +* [Basic Auth](/gateway/{{page.release}}/configure/auth/kong-manager/basic/) +* [OIDC](/gateway/{{page.release}}/configure/auth/kong-manager/oidc-mapping/) +* [LDAP](/gateway/{{page.release}}/configure/auth/kong-manager/ldap/) + +In addition to the Authentication Plugins above, the new +[Sessions Plugin](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/) +is now required when RBAC is enabled. It sends HTTP cookies to authenticate +client requests and maintain session information. + +The Sessions Plugin requires a secret and is configured +securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, +`cookie_samesite` must be set to `off`. +Learn more about these properties in +[Session Security in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#session-security), +and see [example configurations](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +## Access Control with Roles and Workspaces + +An Admin belongs to a Workspace and should have at least one Role +with a set of Permissions. If an Admin is in a Workspace *without* +a Role, they will not have the ability to see or interact with anything. + +By creating separate +[Workspaces](/gateway/{{page.release}}/configure/auth/kong-manager/workspaces/), + an organization with multiple teams can segment its Kong cluster so that + different teams do not have access to each other's Kong entities. + +{{site.base_gateway}} implements Role-Based Access Control +([RBAC](/gateway/{{page.release}}/configure/auth/rbac/)). +Admins are assigned Roles that have clearly defined Permissions. A +Super Admin has the ability to: + +* Further customize Permissions +* Create entirely new Roles +* Invite or deactivate Admins +* Assign or revoke their Roles + +In Kong Manager, limiting Permissions also restricts the visibility of the +application interface and navigation. Learn more about RBAC in Kong Manager in +our guide +[RBAC in Kong Manager](/gateway/{{page.release}}/configure/auth/rbac/). diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/ldap.md b/app/gateway/2.7.x/configure/auth/kong-manager/ldap.md new file mode 100644 index 000000000000..b8b5225740b7 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/ldap.md @@ -0,0 +1,67 @@ +--- +title: Enable LDAP for Kong Manager +badge: enterprise +--- + +{{site.base_gateway}} offers the ability to bind authentication for Kong Manager +*Admins* to a company's Active Directory using the +[LDAP Authentication Advanced plugin](/hub/kong-inc/ldap-auth-advanced). + +Using the configuration below, it is unnecessary to +manually apply the LDAP plugin; the configuration alone will enable LDAP +Authentication for Kong Manager. + +## Enable LDAP + +Ensure Kong is configured with the following properties either in the +configuration file or using environment variables: + +``` +admin_gui_auth = ldap-auth-advanced +enforce_rbac = on +admin_gui_session_conf = { "secret":"set-your-string-here" } +admin_gui_auth_conf = { \ + "anonymous":"", \ + "attribute":"", \ + "bind_dn":"", \ + "base_dn":"", \ + "cache_ttl": 2, \ + "consumer_by":["username", "custom_id"], \ + "header_type":"Basic", \ + "keepalive":60000, \ + "ldap_host":"", \ + "ldap_password":"", \ + "ldap_port":389, \ + "start_tls":false, \ + "timeout":10000, \ + "verify_ldap_host":true \ +} +``` + +* `"attribute":""`: The attribute used to identify LDAP users + * For example, to map LDAP users to admins by their username, `"attribute":"uid"` +* `"bind_dn":""`: LDAP Bind DN (Distinguished Name) + * Used to perform LDAP search of user. This `bind_dn` should have permissions to search + for the user being authenticated. + * For example, `uid=einstein,ou=scientists,dc=ldap,dc=com` +* `"base_dn":""`: LDAP Base DN (Distinguished Name) + * For example, `ou=scientists,dc=ldap,dc=com` +* `"ldap_host":""`: LDAP host domain + * For example, `"ec2-XX-XXX-XX-XXX.compute-1.amazonaws.com"` +* `"ldap_password":""`: LDAP password + * *Note*: As with any configuration property, sensitive information may be set as an + environment variable instead of being written directly in the configuration file. + +The **Sessions Plugin** requires a secret and is configured securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#session-security), and see [example configurations](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +After starting Kong with the desired configuration, you can create new *Admins* +whose usernames match those in the AD. Those users will then be able to accept +invitations to join Kong Manager and log in with their LDAP credentials. + +### Using Service Directory Mapping on the CLI + +{% include /md/gateway/ldap-service-directory-mapping.md %} diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/networking.md b/app/gateway/2.7.x/configure/auth/kong-manager/networking.md new file mode 100644 index 000000000000..50c7d72d3cf0 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/networking.md @@ -0,0 +1,106 @@ +--- +title: Default and Custom Networking Configuration for Kong Manager +badge: enterprise +--- + +## Default Configuration + +By default, Kong Manager starts up without authentication (see +[`admin_gui_auth`]), and it assumes that the Admin API is available +on port 8001 (see [Default Ports](/gateway/{{page.release}}/plan-and-deploy/default-ports/) of the same host that serves +Kong Manager. + +## Custom Configuration + +Common configurations to enable are + +* Serving Kong Manager from a dedicated Kong node + + When Kong Manager is on a dedicated Kong node, it must make + external calls to the Admin API. Set [`admin_api_uri`] to the + location of your Admin API. + +* Securing Kong Manager through a **Kong Authentication Plugin** + + When Kong Manager is **secured through an Authentication Plugin** + and _not_ on a dedicated node, it makes calls to the Admin API on + the same host. By default, the Admin API listens on ports 8001 and + 8444 on localhost. Change [`admin_listen`] if necessary, or set + [`admin_api_uri`]. + +{% include_cached /md/admin-listen.md release=page.release desc='short' %} + +* Securing Kong Manager and serving it from a dedicated node + + When Kong Manager is **secured and served from a dedicated node**, + set [`admin_api_uri`] to the location of the Admin API. + +The table below summarizes which properties to set (or defaults to +verify) when configuring Kong Manager connectivity to the Admin API. + +| authentication enabled | local API | remote API | auth settings | +|------------------------|--------------|---------------|---------------------------------------------------| +| yes | [`admin_listen`] | [`admin_api_uri`] | [`admin_gui_auth`], [`enforce_rbac`], [`admin_gui_auth_conf`], [`admin_gui_session_conf`] | +| no | [`admin_listen`] | [`admin_api_uri`] | n/a | + +To enable authentication, configure the following properties: + +* [`admin_gui_auth`] set to the desired plugin +* [`admin_gui_auth_conf`] (optional) +* [`admin_gui_session_conf`] set to the desired configuration +* [`enforce_rbac`] set to `on` + +{:.important} +> **Important:** When Kong Manager authentication is enabled, RBAC must be turned +on to enforce authorization rules. Otherwise, whoever can log in +to Kong Manager can perform any operation available on the Admin API. + +## TLS Certificates + +By default, if Kong Manager’s URL is accessed over HTTPS _without_ a certificate issued by a CA, it will +receive a self-signed certificate that modern web browsers will not trust, preventing the application +from accessing the Admin API. + +In order to serve Kong Manager over HTTPS, use a trusted certificate authority to issue TLS certificates, +and have the resulting `.crt` and `.key` files ready for the next step. + +1) Move `.crt` and `.key` files into the desired directory of the Kong node. + +2) Point [`admin_gui_ssl_cert`] and [`admin_gui_ssl_cert_key`] at the absolute paths of the certificate and key. + +``` +admin_gui_ssl_cert = /path/to/test.crt +admin_gui_ssl_cert_key = /path/to/test.key +``` + +3) Ensure that `admin_gui_url` is prefixed with `https` to use TLS, e.g., + +``` +admin_gui_url = https://test.com:8445 +``` + +### Using https://localhost + +If serving Kong Manager on localhost, it may be preferable to use HTTP as the protocol. If also using RBAC, +set `cookie_secure=false` in `admin_gui_session_conf`. The reason to use HTTP for `localhost` is that +creating TLS certificates for `localhost` requires more effort and configuration, and there may not be any +reason to use it. The adequate use cases for TLS are (1) when data is in transit between hosts, or (2) +when testing an application with [mixed content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) +(which Kong Manager does not use). + +External CAs cannot provide a certificate since no one uniquely owns `localhost`, nor is it rooted in a top-level +domain (e.g., `.com`, `.org`). Likewise, self-signed certificates will not be trusted in modern browsers. Instead, +it is necessary to use a private CA that allows you to issue your own certificates. Also ensure that the SSL state +is cleared from the browser after testing to prevent stale certificates from interfering with future access to +`localhost`. + + +[`admin_gui_auth`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_auth +[`admin_gui_ssl_cert`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_ssl_cert +[`admin_gui_ssl_cert_key`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_ssl_cert_key +[`default_ports`]: /gateway/{{page.release}}/plan-and-deploy/default-ports +[`admin_api_uri`]: /gateway/{{page.release}}/reference/configuration/#admin_api_uri +[`admin_gui_auth_conf`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_auth_conf +[`enforce_rbac`]: /gateway/{{page.release}}/reference/configuration/#enforce_rbac +[`admin_listen`]: /gateway/{{page.release}}/reference/configuration/#admin_listen +[`admin_gui_session_conf`]: /gateway/{{page.release}}/reference/configuration/#admin_gui_session_conf diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/oidc-mapping.md b/app/gateway/2.7.x/configure/auth/kong-manager/oidc-mapping.md new file mode 100644 index 000000000000..1c14a6d08501 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/oidc-mapping.md @@ -0,0 +1,179 @@ +--- +title: OIDC Authenticated Group Mapping +badge: enterprise +--- + +Using Kong's [OpenID Connect plugin](/hub/kong-inc/openid-connect/) (OIDC), you can map identity provider (IdP) +groups to Kong roles. Adding a user to Kong in this way gives them access to +Kong based on their group in the IdP. + +Admin accounts are now created automatically +when you map your identity provider (IdP) groups to Kong roles. You do +not need to create the users, groups, and roles separately. These users then accept invitations to join +Kong Manager and log in with their IdP credentials. + +{:.important} +> **Important:** In v2.7.x, the `admin_claim` parameter replaces the `consumer_claim` parameter required by +previous versions. + +If an admin's group changes in the IdP, their Kong admin account's associated +role also changes in {{site.base_gateway}} the next time they log in to Kong +Manager. The mapping removes the task of manually managing access in +{{site.base_gateway}}, because it makes the IdP the system of record. + +## Prerequisites + +* An IdP with an authorization server and users with groups assigned +* [{{site.ee_product_name}} installed and configured](/gateway/{{page.release}}/install-and-run/) +* Kong Manager enabled +* RBAC enabled +* (Kubernetes) [Helm](https://helm.sh/docs/intro/install/) installed + +## Apply OIDC auth mapping to {{site.base_gateway}} + +In the following examples, you specify the `admin_claim` and `authenticated_groups_claim` parameters +to identify which admin value and role name to map from the IdP to {{site.base_gateway}}. + +The `admin_claim` value specifies which IdP username value should map to Kong Manager. +The username and password are required for the user to log into the IdP. + +The `authenticated_groups_claim` value specifies which IdP claim should be used to assign {{site.base_gateway}} roles to the +specified {{site.base_gateway}} admin. + +This value depends on your IdP -- for example, Okta configures claims for `groups`, and another IdP might configure them as `roles`. + +In the IdP, the group claim value must follow the format `:`. + +For example, if `"authenticated_groups_claim": ["groups"]` is specified, and in the IdP `groups:["default:super-admin"]` is specified, the administrators specified in `admin_claim` are assigned to the super-admin role in the default {{site.base_gateway}} workspace. + +If the mapping does not work as expected, decode the JWT that's created by your IdP, and make sure that the admin ID token includes the key:value pair `groups:["default:super-admin"]` for the case of this example, or the appropriate claim name and claim value as set in your IdP. + +{% navtabs %} +{% navtab Kubernetes with Helm %} + +1. Create a configuration file for the OIDC plugin and save it as +`admin_gui_auth_conf`. + + Provide your own values for all fields indicated by curly braces (`{}`): + + ```json + { + "issuer": "{YOUR_IDP_URL}", + "admin_claim": "email", + "client_id": ["{CLIENT_ID}"], + "client_secret": ["{CLIENT_SECRET}"], + "authenticated_groups_claim": ["{CLAIM_NAME}"], + "ssl_verify": false, + "leeway": 60, + "redirect_uri": ["{YOUR_REDIRECT_URI}"], + "login_redirect_uri": ["{YOUR_LOGIN_REDIRECT_URI}"], + "logout_methods": ["GET", "DELETE"], + "logout_query_arg": "logout", + "logout_redirect_uri": ["{YOUR_LOGOUT_REDIRECT_URI}"], + "scopes": ["openid","profile","email","offline_access"], + "auth_methods": ["authorization_code"] + } + ``` + + For detailed descriptions of all OIDC parameters, see the + [OpenID Connect parameter reference](/hub/kong-inc/openid-connect/#configuration-parameters). + +2. Create a secret from the file you just created: + + ```sh + kubectl create secret generic kong-idp-conf --from-file=admin_gui_auth_conf -n kong + ``` + +3. Update the RBAC section of the deployment `values.yml` file with the +following parameters: + + ```yaml + rbac: + enabled: true + admin_gui_auth: openid-connect + session_conf_secret: kong-session-conf + admin_gui_auth_conf_secret: kong-idp-conf + ``` + +4. Using Helm, upgrade the deployment with your YAML filename: + + ```sh + helm upgrade --install kong-ee kong/kong -f ./myvalues.yaml -n kong + ``` +{% endnavtab %} +{% navtab Docker %} + +If you have a Docker installation, run the following command to set the needed +environment variables and reload the {{site.base_gateway}} configuration. + + Provide your own values for all fields indicated by curly braces (`{}`): + +```sh +$ echo " + KONG_ENFORCE_RBAC=on \ + KONG_ADMIN_GUI_AUTH=openid-connect \ + KONG_ADMIN_GUI_AUTH_CONF='{ + \"issuer\": \"{YOUR_IDP_URL}\", + \"admin_claim\": \"email\", + \"client_id\": [\"\"], + \"client_secret\": [\"\"], + \"authenticated_groups_claim\": [\"{CLAIM_NAME}\"],, + \"ssl_verify\": false, + \"leeway\": 60, + \"redirect_uri\": [\"{YOUR_REDIRECT_URI}\"], + \"login_redirect_uri\": [\"{YOUR_LOGIN_REDIRECT_URI}\"], + \"logout_methods\": [\"GET\", \"DELETE\"], + \"logout_query_arg\": \"logout\", + \"logout_redirect_uri\": [\"{YOUR_LOGOUT_REDIRECT_URI}\"], + \"scopes\": [\"openid\",\"profile\",\"email\",\"offline_access\"], + \"auth_methods\": [\"authorization_code\"] + }' kong reload exit" | docker exec -i {KONG_CONTAINER_ID} /bin/sh +``` + +Replace `{KONG_CONTAINER_ID}` with the ID of your container. + +For detailed descriptions of all the parameters used here, and many other customization options, +see the [OpenID Connect parameter reference](/hub/kong-inc/openid-connect/#configuration-parameters). + +{% endnavtab %} +{% navtab kong.conf %} + +1. Navigate to your `kong.conf` file. + +2. With RBAC enabled, add the `admin_gui_auth` and `admin_gui_auth_conf` +properties to the file. + + Provide your own values for all fields indicated by curly braces (`{}`): + + ``` + enforce_rbac = on + admin_gui_auth = openid-connect + admin_gui_auth_conf = { + "issuer": "{YOUR_IDP_URL}", + "admin_claim": "email", + "client_id": ["{CLIENT_ID}"], + "client_secret": ["{CLIENT_SECRET}"], + "authenticated_groups_claim": ["{CLAIM_NAME}"], + "ssl_verify": false, + "leeway": 60, + "redirect_uri": ["{YOUR_REDIRECT_URI}"], + "login_redirect_uri": ["{YOUR_LOGIN_REDIRECT_URI}"], + "logout_methods": ["GET", "DELETE"], + "logout_query_arg": "logout", + "logout_redirect_uri": ["{YOUR_LOGOUT_REDIRECT_URI}"], + "scopes": ["openid","profile","email","offline_access"], + "auth_methods": ["authorization_code"] + } + ``` + + For detailed descriptions of all the parameters used here, and many other + customization options, see the [OpenID Connect parameter reference](/hub/kong-inc/openid-connect/#configuration-parameters). + +3. Restart {{site.base_gateway}} to apply the file. + + ```sh + $ kong restart -c /path/to/kong.conf + ``` + +{% endnavtab %} +{% endnavtabs %} diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/reset-password.md b/app/gateway/2.7.x/configure/auth/kong-manager/reset-password.md new file mode 100644 index 000000000000..17d59c2c8167 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/reset-password.md @@ -0,0 +1,61 @@ +--- +title: Reset Passwords and RBAC Tokens in Kong Manager +badge: enterprise +--- + +## Passwords and RBAC Tokens + +For authentication, Kong uses two different credentials for **Admins**: + +1. An **Admin** uses a **password** to log in to Kong Manager. +2. An **Admin** uses an **RBAC token** to make requests to the Kong Admin API. + +If (and only if) using **Basic Authentication**, an Admin may reset their **password** from within Kong Manager. Since **LDAP** and **OIDC Authentication** imply that an organization stores and manages passwords outside of Kong, password reset is not possible with either type. + +Since a hash of each **RBAC token** is stored in Kong, then regardless of the Authentication option selected, an **Admin** may reset their **RBAC token** from within Kong Manager. Note that to support confidentiality, **RBAC tokens** are hashed and cannot be retrieved after they are created. If a user forgets the token, the only recourse is to reset it. + +## How to Reset a Forgotten Password in Kong Manager + +Prerequisites: + +* `enforce_rbac = on` +* `admin_gui_auth = basic-auth` +* SMTP is configured to send emails + +Steps: + +1. At the login page, click **Forgot Password** beneath the login field. +2. Enter the email address associated with the account. +3. Click the link from the email. +4. Reset the password. Note that you will need to provide it again immediately after the reset is complete. +5. Log in with the new password. + +## How to Reset a Password from within Kong Manager + +Prerequisites: + +* `enforce_rbac = on` +* `admin_gui_auth = basic-auth` +* [`admin_gui_session_conf` is configured](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/). +* Already logged in to Kong Manager + +Steps: + +1. At the **top right corner**, after hovering over the **account name**, select **Profile**. +2. In the **Reset Password** section, fill in the fields and click the **Reset Password** button. + +## How to Reset an RBAC Token in Kong Manager + +Prerequisites: + +* `enforce_rbac = on` +* [`admin_gui_auth` is set](/gateway/{{page.release}}/configure/auth/kong-manager/). +* [`admin_gui_session_conf` is configured](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/). +* Already logged in to Kong Manager + +Steps: + +1. At the **top right corner**, after hovering over the **account name**, select **Profile**. +2. In the **Reset RBAC Token** section at the bottom, click **Reset Token**. +3. Type in a new token and click **Reset**. +4. To copy the token, click the **Copy** button at the right. diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/sessions.md b/app/gateway/2.7.x/configure/auth/kong-manager/sessions.md new file mode 100644 index 000000000000..ca8a128df3aa --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/sessions.md @@ -0,0 +1,104 @@ +--- +title: Sessions in Kong Manager +badge: enterprise +--- + +## How does the Sessions Plugin work in Kong Manager? + +When a user logs in to Kong Manager with their credentials, the Sessions Plugin +will create a session cookie. The cookie is used for all subsequent requests and +is valid to authenticate the user. The session has a limited duration and renews +at a configurable interval, which helps prevent an attacker from obtaining and + using a stale cookie after the session has ended. + +The Session configuration is secure by default, which may +[require alteration](#session-security) if using HTTP or different domains for +the Admin API and Kong Manager. Even if an attacker were to obtain a stale +cookie, it would not benefit them since the cookie is encrypted. The encrypted +session data may be stored either in Kong or the cookie itself. + +## Configuration to Use the Sessions Plugin with Kong Manager + +To enable sessions authentication, configure the following: + +``` +enforce_rbac = on +admin_gui_auth = +admin_gui_session_conf = { + "secret":"", + "cookie_name":"", + "storage":"", + "cookie_lifetime":, + "cookie_renew": + "cookie_secure": + "cookie_samesite":"" +} +``` + +* `"cookie_name":""`: The name of the cookie + * For example, `"cookie_name":"kong_cookie"` +* `"secret":""`: The secret used in keyed HMAC generation. Although + the **Session Plugin's** default is a random string, the `secret` _must_ be + manually set for use with Kong Manager since it must be the same across all + Kong workers/nodes. +* `"storage":""`: Where session data is stored. It is `"cookie"` by default, but may be more secure if set to `"kong"` since access to the database would be required. +* `"cookie_lifetime":`: The duration (in seconds) that the session will remain open; 3600 by default. +* `"cookie_renew":`: The duration (in seconds) of a session remaining at which point + the Plugin renews the session; 600 by default. +* `"cookie_secure":`: `true` by default. See [Session Security](#session-security) for + exceptions. +* `"cookie_samesite":""`: `"Strict"` by default. See [Session Security](#session-security) for + exceptions. + + +{:.important} +> **Important:** The following properties must **not** be altered from default for use with Kong Manager:* +* `logout_methods` +* `logout_query_arg` +* `logout_post_arg` + +For detailed descriptions of each configuration property, learn more in the +[Session Plugin documentation](/hub/kong-inc/session). + +## Session Security + +The Session configuration is secure by default, so the cookie uses the +[Secure, HttpOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies), +and [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies) +directives. + +The following properties must be altered depending on the protocol and domains in use: +* If using HTTP instead of HTTPS: `"cookie_secure": false` +* If using different domains for the Admin API and Kong Manager: `"cookie_samesite": "off"` + +{:.important} +> **Important:** Sessions are not invalidated when a user logs out if `"storage": "cookie"` (the default) is used. In that case, the cookie is deleted client-side. Only when session data is stored server-side with `"storage": "kong"` set is the session actively invalidated. + + +## Example Configurations + +If using HTTPS and hosting Kong Manager and the Admin API from the same domain, +the following configuration could be used for Basic Auth: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { + "cookie_name":"$4m04$" + "secret":"change-this-secret" + "storage":"kong" +} +``` + +In testing, if using HTTP, the following configuration could be used instead: + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = { + "cookie_name":"04tm34l" + "secret":"change-this-secret" + "storage":"kong" + "cookie_secure":false +} +``` diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/super-admin.md b/app/gateway/2.7.x/configure/auth/kong-manager/super-admin.md new file mode 100644 index 000000000000..14b732a0b3b1 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/super-admin.md @@ -0,0 +1,53 @@ +--- +title: Create a Super Admin +badge: enterprise +--- + +If you seeded a **Super Admin** at the time of running +migrations by passing `KONG_PASSWORD`, you may log in to Kong Manager +with the `kong_admin` username. + +Otherwise, if `enforce_rbac=off`, you may create your first +**Super Admin** within Kong Manager itself. + +You may also use this guide to create additional **Super Admins** once +you have an account and `enforce_rbac=on`. + +1. Go to the "Teams" tab in Kong Manager. + +2. Click "+ Invite Admin" and fill out the form. + +3. Give the user the `super-admin` role in the `default` workspace. + +4. Return to the "Organization" page, and in the "Invited" section, +click the email address of the user in order to view them. + +5. Click "Generate Registration Link". + +6. Copy the link for later use after completing the account setup. + +{:.important} +> **Important:** Kong Manager does not support entity-level RBAC. Run Kong +Manager on a node where `enforce_rbac` is set to `on` or `off`, but not `both`. + + +## How to Create Your First Super Admin Account Post Installation + +In the event that the default `kong_admin`, **Super Admin**, was not seeded +during the initial database preparation step as defined in +[How To Start {{site.base_gateway}} Securely](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/), +the following steps outline how to create and enable a new Super Admin post +installation. + +1. Follow the instructions outlined above to create a new **Super Admin** user +account and generate a registration link. + +2. Before the link generated above can be used, RBAC and GUI Authentication must +be enabled. Follow the instructions on +[how to enable Basic Auth on Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/basic). + +3. Paste the URL in your browser and you will be asked to create a password for +the newly defined **Super Admin** user on the Kong Manager. + +4. Go to the Kong Manager homepage and you will be prompted to login with the +new ***Super Admin*** credentials. diff --git a/app/gateway/2.7.x/configure/auth/kong-manager/workspaces.md b/app/gateway/2.7.x/configure/auth/kong-manager/workspaces.md new file mode 100644 index 000000000000..45e9dbc24868 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/kong-manager/workspaces.md @@ -0,0 +1,198 @@ +--- +title: Configure Workspaces in Kong Manager +badge: enterprise +--- + +Workspaces enable an organization to segment traffic so that +teams of admins sharing the same Kong cluster are only able to +interact with entities from their groups. Within a workspace, +it is possible to invite admins to a particular team and to +enforce RBAC with roles and permissions that further +delimit the types of actions and entities available to an admin. + +## Prerequisites + +* [`enforce_rbac = on`](/gateway/{{page.release}}/reference/configuration/#enforce_rbac) +* {{site.base_gateway}} has [started](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/) +* Logged in to Kong Manager as a **Super Admin** + +## Default workspace + +When the first Super Admin logs in, they begin in the workspace +named **default**. From here, they may invite admins to manage the default or +any other workspaces. + +## Navigating across workspaces in Kong Manager + +To navigate between workspaces from the **Overview** page, click on any +workspace displayed beneath the **Vitals** chart. + +The list of workspaces may be rendered as cards or a table, +depending on preference. + + +## Create a Workspace + +This guide describes how to create workspaces in Kong +Manager. You can also use the Admin API [`/workspaces/` route](/gateway/{{page.release}}/admin-api/workspaces/reference/#add-workspace) to create a workspace. + +1. Log in as the **Super Admin**. On the **Workspaces** page, click the **New Workspace** +button at the top right to see the **Create Workspace** form. Name and choose a +color / icon for the new Workspace. + + Each workspace name should be unique, + regardless of letter case. For example, naming one + workspace "Payments" and another one "payments" will + create two different workspaces that appear identical. + + Do not name workspaces the same as these major API names (paths) + in Admin API: + + ``` + • Admins + • Certificates + • Consumers + • Plugins + • Portal + • Routes + • Services + • SNIs + • Upstreams + • Vitals + ``` + +2. Click the **Create New Workspace** button. Upon creation, the application will +navigate to the new Workspace's dashboard. + +## Edit a workspace + +1. In the workspace you want to edit, navigate to the **Dashboard** page. + +1. Near the top right, click the **Settings** button. This button takes you to the **Edit Workspace** page. + +1. Here, you can edit the workspace avatar and avatar background color. + +1. Click **Update Workspace** to save. + +## Delete a workspace + +### Wipe workspace data +To delete a workspace, *all data* must first be deleted from the workspace. +Choose one of the following methods. + +{% navtabs %} +{% navtab Kong Manager %} +Using Kong Manager, complete the following: + +1. Manually delete all files via **Dev Portal** > **Editor**. You cannot delete folders at this time, but deleting +all files from a folder will remove the folder. +1. Turn off the Dev Portal. Go to Dev Portal **Settings** > **Advanced** > **Turn Off**. +1. Remove all roles from the workspace: + 1. Go to **Teams** in the top navigation. + 1. Navigate to the **Roles** tab. + 1. Click **View** on the workspace you want to delete. + 1. Go to each role entry and click **Edit**. + 1. In the entry detail page, click **Delete Role**. A confirmation modal will appear. Click **Delete Role** again. + +{% endnavtab %} +{% navtab Admin API %} + +1. Delete all Dev Portal files associated with the workspace: + + ```bash + curl -i -X DELETE http://localhost:8001/{WORKSPACE_NAME}/files + ``` + +1. Turn off the Dev Portal for the workspace: + + ```bash + curl -X PATCH http://localhost:8001/workspaces/{WORKSPACE_NAME} \ + --data "config.portal=false" + ``` + +1. [Delete each role](/gateway/{{page.release}}/admin-api/rbac/reference/#delete-a-role) +from the workspace: + + ```bash + curl -i -X DELETE http://localhost:8001/{WORKSPACE_NAME}/rbac/roles/{ROLE_NAME|ROLE_ID} + ``` +{% endnavtab %} +{% navtab Portal CLI %} + +1. Delete all Dev Portal files associated with the workspace: + + ```sh + portal wipe WORKSPACE_NAME + ``` + +2. Turn off the Dev Portal for the workspace: + + ```sh + portal disable WORKSPACE_NAME + ``` + +3. Delete each role from the workspace. You can't complete this step using the +Portal CLI, so switch to either the *Kong Manager* or *Admin API* tab and complete +step 3. + +{% endnavtab %} +{% endnavtabs %} + +### Delete a clean workspace + +If your workspace is clean, you can delete it using the Kong Manager GUI or the +Kong Admin API. If not, see the previous section to [wipe workspace data](#wipe-workspace-data). + +{% navtabs %} +{% navtab Kong Manager %} + +1. In the workspace you want to delete, navigate to the **Dashboard** page. + +1. Near the top right, click the **Settings** button. This button takes you to the **Edit Workspace** page. + +1. Click **Delete** in the bottom right corner. + + The deletion will fail if you have any data in your workspace. + +{% endnavtab %} +{% navtab Admin API %} + +Send a `DELETE` request to the Kong Admin API: + +```sh +curl -i -X DELETE http://localhost/workspaces/{WORKSPACE_NAME|WORKSPACE_ID} +``` + +The deletion will fail if you have any data in your workspace. + +If it is successful, you should see the following response: + +``` +HTTP 204 No Content +``` + +{% endnavtab %} +{% endnavtabs %} + +## Workspace Access + +If a role does not have permission to access entire endpoints within +a workspace, the admin assigned to that role will not be +able to see the related navigation links. + +To set up access: +1. Open Kong Manager. +2. On the left sidebar, click the **Admins** link in the +**Security** section. + + If the sidebar is collapsed, hover over + the **security badge icon** at the bottom and click the + **Admins** link. + +The Admins page displays a list of current admins and +roles. Four default roles specific to the new +workspace are already visible, and new roles specific +to the workspace can be assigned from this page. + +For more information about admins and roles, see +[RBAC in Kong Manager](/gateway/{{page.release}}/configure/auth/rbac/). diff --git a/app/gateway/2.7.x/configure/auth/oidc-auth0.md b/app/gateway/2.7.x/configure/auth/oidc-auth0.md new file mode 100644 index 000000000000..02174544d07c --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/oidc-auth0.md @@ -0,0 +1,49 @@ +--- +title: OpenID Connect with Auth0 +badge: enterprise +--- + +This guide covers an example OpenID Connect plugin configuration to authenticate headless service consumers using Auth0's identity provider. + +## Auth0 IDP Configuration + +This configuration will use a [client credentials grant][client-credentials-grant] as it is non-interactive, and because we expect clients to authenticate on behalf of themselves, not an end-user. To do so, you will need to [create an Auth0 API][create-auth0-api] and a [non-interactive client][non-interactive-client]. + +### API Configuration + +When creating your API, you will need to specify an Identifier. Using the URL that your consumer makes requests to is generally appropriate, so this will typically be the hostname/path combination configured as an API in Kong. + +After creating your API, you will also need to add the `openid` scope at `https://manage.auth0.com/#/apis//scopes`. + +### Client Configuration + +You will need to authorize your client to access your API. Auth0 will prompt you to do so after client creation if you select the API you created previously from the client's Quick Start menu. After toggling the client to Authorized, expand its authorization settings and enable the `openid` scope. + +## Kong Configuration + +If you have not done so already, [create a **Service**][add-service] to protect. The `url` configuration should match the Identifier you used when configuring Auth0. + +Add an OpenID plugin configuration using the parameters in the example below using an HTTP client or Kong Manager. Auth0's token endpoint [requires passing the API identifier in the `audience` parameter][audience-required], which must be added as a custom argument: + +```bash +curl -i -X POST http://localhost:8001/kong-admin/services/{SERVICE_NAME}/plugins \ + --data name="openid-connect" \ + --data config.auth_methods="client_credentials" \ + --data config.issuer="https://.auth0.com/.well-known/openid-configuration" \ + --data config.token_post_args_names="audience" \ + --data config.token_post_args_values="https://example.com/" +``` + +## Downstream configuration + +The service accessing your resource will need to pass its credentials to Kong. It can do so via HTTP basic authentication, query string arguments, or parameters in the request body. Basic authentication is generally preferable, as credentials in a query string will be present in Kong's access logs (and possibly in other infrastructure's access logs, if you have HTTP-aware infrastructure in front of Kong) and credentials in request bodies are limited to request methods that expect +client payloads. + +For basic authentication, use your client ID as the username and your client secret as the password. For the other methods, pass them as parameters named `client_id` and `client_secret`, respectively. + + +[client-credentials-grant]: https://auth0.com/docs/api-auth/tutorials/client-credentials +[create-auth0-api]: https://auth0.com/docs/apis#how-to-configure-an-api-in-auth0 +[non-interactive-client]: https://auth0.com/docs/clients +[add-service]: /gateway/{{page.release}}/admin-api/#service-object +[audience-required]: https://auth0.com/docs/api/authentication#client-credentials diff --git a/app/gateway/2.7.x/configure/auth/oidc-azuread.md b/app/gateway/2.7.x/configure/auth/oidc-azuread.md new file mode 100644 index 000000000000..5acb2da6aef0 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/oidc-azuread.md @@ -0,0 +1,133 @@ +--- +title: OpenID Connect with Azure AD +badge: enterprise +--- + +This guide covers an example OpenID Connect plugin configuration to authenticate +browser clients using an Azure AD identity provider. + +For information about configuring OIDC using Azure as an Identity provider +in conjunction with the Application Registration plugin, see +[Set Up External Portal Application Authentication with Azure AD and OIDC](/gateway/{{page.release}}/developer-portal/administration/application-registration/azure-oidc-config). + +## Prerequisites + +Because OpenID Connect deals with user credentials, all transactions should take place over HTTPS. +Although user passwords for third party identity providers are only submitted to +those providers and not Kong, authentication tokens do grant access to a subset of +user account data and protected APIs, and should be secured. As such, you should +make Kong's proxy available via a fully-qualified domain name and [add a certificate][add-certificate] for it. + +## Kong Configuration + +If you have not yet [added a **Route** and a **Service**][add-service], go ahead +and do so. Again, note that you should be able to secure this route with HTTPS, +so use a hostname you have a certificate for. Add a location handled by your +Route as an authorized redirect URI in Azure (under the **Authentication** section of your app registration). + +## Azure AD IdP Configuration + +You must [register an app][azure-create-app] in your Azure AD configuration and [add a client secret credential][azure-client-secret] that Kong will use to access it. You must also configure a redirect URI that is handled by your Route. + +Azure AD provides two interfaces for its OAuth2/OIDC-related endpoints: v1.0 and v2.0. +Support for some legacy v1.0 behavior is still available on v2.0, including use of v1.0 tokens by +default, which is not compatible with Kong's OIDC implementation. To force Azure AD to use v2.0 tokens, +[edit your application manifest][azure-manifest] and set `accessTokenAcceptedVersion` to `2` and +include a `YOUR_CLIENT_ID/.default` scope in your plugin configuration as shown below. + +## Plugin Configuration + +Add a plugin with the configuration below to your Route using an HTTP client or [Kong Manager][enable-plugin]. + +```bash +$ curl -i -X POST https://admin.kong.example/routes/ROUTE_ID/plugins --data name="openid-connect" \ + --data config.issuer="https://login.microsoftonline.com/YOUR_DIRECTORY_ID/v2.0/.well-known/openid-configuration" \ + --data config.client_id="YOUR_CLIENT_ID" \ + --data config.client_secret="YOUR_CLIENT_SECRET" \ + --data config.redirect_uri="https://example.com/api" \ + --data config.scopes="openid" \ + --data config.scopes="email" \ + --data config.scopes="profile" \ + --data config.scopes="YOUR_CLIENT_ID/.default" \ + --data config.verify_parameters="false" +``` + +Some of the configurations above must use values specific to your environment: + +* The `issuer` URL can be retrieved by clicking the **Endpoints** button on your app registration's **Overview** page. +* `redirect_uri` should be the URI you specified earlier when configuring your app. You can +add one via the **Authentication** section of the app settings if you did not add one initially. +* For `client_id` and `scopes`, replace `YOUR_CLIENT_ID` with the client ID shown on the app **Overview** page. +* For `client_secret`, replace `YOUR_CLIENT_SECRET` with the URL-encoded representation of the +secret you created earlier in the **Certificates & secrets** section. Azure AD secrets +often include reserved URL characters, which cURL might handle incorrectly if they are not URL-encoded. + +Visiting a URL matched by that route in a browser will now redirect to Microsoft's +authentication site and return you to the redirect URI after authenticating. + +### Access Restrictions + +The configuration above allows users to authenticate and access the Route even though no +Consumer was created for them: any user with a valid account in the directory +will have access to the Route. The OIDC plugin allows this as the simplest +authentication option, but you might want to restrict access further. There are several options for this: + +- Domain Restrictions +- Consumer Mapping +- Pseudo-Consumer Mapping + +#### Domain Restrictions + +Azure AD does not provide identity tokens with the `hd` claim, and as such, the +OIDC plugin's `domains` configuration cannot restrict users based on their domain. +Using a [single-tenant][azure-tenant] application will restrict access to users +in your directory only. Multi-tenant apps allow users with Microsoft accounts +from other directories and optionally any Microsoft account (e.g., live.com or Xbox accounts) to sign in. + +#### Consumer Mapping + +If you need to interact with other Kong plugins using Consumer information, you can +add configuration that maps account data received from the identity provider to a Kong Consumer. +For this example, the user's Azure AD account GUID is mapped to a Consumer by setting +it as the `custom_id` on their Consumer: + +```bash +$ curl -i -X POST http://admin.kong.example/consumers/ \ + --data username="Yoda" \ + --data custom_id="e5634b31-d67f-4661-a6fb-b6cb77849bcf" + +$ curl -i -X PATCH http://admin.kong.example/plugins/OIDC_PLUGIN_ID \ + --data config.consumer_by="custom_id" \ + --data config.consumer_claim="oid" +``` + +Now, if a user logs into an Azure AD account with the GUID `e5634b31-d67f-4661-a6fb-b6cb77849bcf`, +Kong will apply configuration associated with the Consumer `Yoda` to their requests. + +This also requires that clients login using an account mapped to some Consumer, +which may not be desirable (e.g., you apply OpenID Connect to a Service, but only +use plugins requiring a Consumer on some routes). To deal with this, you can set +the `anonymous` parameter in your OIDC plugin configuration to the ID of a generic +Consumer, which will then be used for all authenticated users that cannot be mapped +to some other Consumer. You can alternately set `consumer_optional` to `true` to allow +similar logins without mapping an anonymous Consumer. + +#### Pseudo-Consumer Mapping + +For plugins that typically require Consumers, the OIDC plugin can provide a consumer ID +based on the value of a claim without mapping to an actual Consumer. Setting `credential_claim` +to a claim [in your plugin configuration][credential-claim] will extract the value +of that claim and use it where Kong would normally use a consumer ID. Note that this +may not work with all consumer-related functionality. + +Similarly, setting `authenticated_groups_claim` will extract that claim's value and use it as a group for the ACL plugin. + +[azure-client-secret]: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-credentials-to-your-web-application +[azure-create-app]: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app +[azure-manifest]: https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-app-manifest#configure-the-app-manifest +[azure-tenant]: https://docs.microsoft.com/en-us/azure/active-directory/develop/single-and-multi-tenant-apps +[add-certificate]: /gateway/{{page.release}}/admin-api/#add-certificate +[add-service]: /gateway/{{page.release}}/admin-api/#service-object +[oidc-id-token]: http://openid.net/specs/openid-connect-core-1_0.html#IDToken +[credential-claim]: /hub/kong-inc/openid-connect/#configcredential_claim +[enable-plugin]: /gateway/{{page.release}}/admin-api/#plugin-object diff --git a/app/gateway/2.7.x/configure/auth/oidc-cognito.md b/app/gateway/2.7.x/configure/auth/oidc-cognito.md new file mode 100644 index 000000000000..52cdf21bd990 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/oidc-cognito.md @@ -0,0 +1,194 @@ +--- +title: OpenID Connect with Amazon Cognito +badge: enterprise +--- + +## Amazon Cognito Configuration + +Amazon Cognito has two significant components: Identity Pools and User Pools. Identity Pools are the original functionality deployed in 2014; they mainly use proprietary AWS interfaces and libraries to accomplish the task of authenticating users. Furthermore, Identity Pools have no concept of claims (standard or custom) stored in the system; it is entirely a federated identity construct. User Pools are the more recent addition to the Cognito feature set; User Pools are a multi-tenant LDAP-like user repository combined with an OAuth2 and an OpenID Connect interface. + +In this configuration, we use User Pools. + +1. Log in to AWS Console. +1. Navigate to the Amazon Cognito Service. + +1. Click on **Manage User Pools**. + +1. Click the **Create a user pool** button on the right-hand side. + +1. Enter a pool name; we use “test-pool” for this example. + +1. Click **Step Through Settings**. + +1. Select **Email address or phone number**, and under that, select **Allow email addresses**. Select the following standard attributes as required: email, family name, given name. + +1. Click **Next step**. +1. Accept the defaults for **Password settings**, then click **Next step**. +1. Accept the defaults for **MFA and verifications**, then click **Next step**. +1. Accept the defaults for **Message customizations**, click **Next step**. +1. On the next screen, we are not going to create any tags. Click **Next step**. +1. Select **No** for **Do you want to remember your user’s devices**, then click **Next step**. +1. We can create an application definition later. Keep things simple for now and click **Next step**. +1. We don’t have any need for Triggers or customized Sign Up/Sign In behavior for this example. Scroll down and click **Save Changes**. + +1. Click **Create pool**. Wait a moment for the success message. +1. Make a note of the **Pool ID**. You will need this when configuring the application later. + +## Application Definition + +You need to add an OAuth2 application definition to the User Pool we just created. + +1. Go to the App clients screen in the AWS Cognito management screen for the User Pool we just created. + +1. Click “Add an app client”. + +1. Enter an App client name. This demo is using “kong-api”. + +1. Enter a Refresh token expiration (in days). We will use the default of 30 days. +1. Do not select “Generate client secret”. This example will use a public client. + +1. Do not select any other checkboxes. + +1. Click the “Set attribute read and write permissions” button. + +1. Let’s make this simple and only give the user read and write access to the required attributes. So, uncheck everything except the email, given name, and family name fields. + +1. Click “Create app client”. + +1. Click “Show Details”. + +1. Take note of the App client ID. We will need that later. +1. Go to the App integration -> App client settings screen. +1. Click the “Cognito User Pool” checkbox under Enabled Identity Providers. +1. Add the following to the Callback URLs field: + + ``` + “https://kong-ee:8446/default, https://kong-ee:8447/default/, https://kong-ee:8447/default/auth, https://kong-ee:8443/cognito” + ``` + + Note that AWS Cognito doesn’t support HTTP callback URLs. This field should + include the API and Dev Portal URLs that you want to secure using AWS Cognito. + +1. Click the “Authorization code grant” checkbox under Allowed OAuth Flows. +1. Click the checkboxes next to email, OpenID, aws.cognito.signin.user.admin, and profile. +1. Click the “Save changes” button. +1. Click on the domain name tab. +1. Add a sub-domain name. +1. Click the Check Availability button. +1. As long as it reports “This domain is available”, the name you have chosen will work. +1. Click the “Save changes” button. + +Now that you have created an Amazon Cognito User Pool and Application Definition, we can configure the OpenID Connect plugin in Kong. We can then test integration between Dev Portal and Amazon Cognito. + +Amazon’s OIDC discovery endpoint is available from: +``` +https://cognito-idp..amazonaws.com/ +``` + +For example, in this demo, the OIDC discovery endpoint is: + +``` +https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_ie577myCv/.well-known/openid-configuration +``` + +The OAuth + OIDC debugger is a handy utility that you may use to test the authorization flow before configurations in Kong. + +## OIDC Plugin Configuration + +Identify the Route or Service to be secured. In our example, we created a new route called /cognito to which we added the OpenID Connect plug-in. +The number of options in the plug-in can seem overwhelming but the configuration is rather simple. All you need to do is configure: +* `issuer` - You can use the OIDC discovery endpoint here, e.g. + ``` + https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_ie577myCv/.well-known/openid-configuration + ``` +* `config.client_id` - This is the client ID noted when the application was created +* `config.client_secret` - This is the client secret noted when the application was created. In this demo we are leaving this blank as we didn’t create a client secret. +* `config.auth_methods` - If this is left blank, all flows will be enabled. If only specific flows are in scope, configure the appropriate flows accordingly. + +## Validating the Flows + +You can test the route by accessing URL “https://kong-ee:8443/cognito/anything”, and you should redirect to the Amazon Cognito login page. You need to click “Sign up” link to create a user first using your email address. The application sends a verification code to your email. Once you enter the verification code, Amazon Cognito acknowledges the account. + +You can verify the confirmed user from the Cognito page under “General settings” -> “Users and groups”. + +## Dev Portal Integration + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + +Since AWS Cognito only supports the HTTPS protocol, when you start {{site.base_gateway}}, ensure that HTTPS protocol for Dev Portal is enabled. For example: + +``` +docker run -d --name kong-ee --link kong-ee-database:kong-ee-database \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_CASSANDRA_CONTACT_POINTS=kong-ee-database" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001 , 0.0.0.0:8444 ssl" \ + -e "KONG_PORTAL=on" \ + -e "KONG_ENFORCE_RBAC=off" \ + -e "KONG_ADMIN_GUI_URL=http://kong-ee:8002" \ + -e "KONG_AUDIT_LOG=on" \ + -e "KONG_PORTAL_GUI_PROTOCOL=https" \ + -e "KONG_PORTAL_GUI_HOST=kong-ee:8446" \ + -e "KONG_LICENSE_DATA=$KONG_LICENSE_DATA" \ + -p 8000-8004:8000-8004 \ + -p 8443-8447:8443-8447 \ + kong-ee +``` + +Under Dev Portal settings, select “Open ID Connect” as the authentication plugin. + +Copy and paste the following Auth Config JSON object: + +``` +{ + "leeway": 100, + "consumer_by": [ + "username", + "custom_id", + "id" + ], + "scopes": [ + "openid", + "profile", + "email" + ], + "logout_query_arg": "logout", + "client_id": [ + "1pf00c5or942c2hm37mgv0u509" + ], + "login_action": "redirect", + "logout_redirect_uri": [ + "https://kongdemo.auth.ap-southeast-1.amazoncognito.com/logout?client_id=1pf00c5or942c2hm37mgv0u509&logout_uri=kong-ee:8446/default" + ], + "login_tokens": {}, + "login_redirect_uri": [ + "https://kong-ee:8446/default" + ], + "forbidden_redirect_uri": [ + "https://kong-ee:8446/default/unauthorized" + ], + "ssl_verify": false, + "issuer": "https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_ie577myCv/.well-known/openid-configuration", + "logout_methods": [ + "GET" + ], + "consumer_claim": [ + "email" + ], + "login_redirect_mode": "query", + "redirect_uri": [ + "https://kong-ee:8447/default/auth" + ] +} +``` + +To log out the user completely, we need to use the logout endpoint provided by Cognito (https://docs.aws.amazon.com/cognito/latest/developerguide/logout-endpoint.html). Therefore, in the above configuration, we have passed in Cognito logout endpoint of logout redirect URL. + +Please also note that the developer signed up from Dev Portal doesn’t get created in Cognito automatically. Therefore, developer sign-up is a two-step process: +* The developer signs up from Dev Portal itself, so a Kong Admin needs to approve the developer access. +* The developer signs up from Amazon Cognito. Please make sure that you use the _same email address_ for both sign-ups. +Now you should be able to login to Developer Portal using the Amazon Cognito user and credential. diff --git a/app/gateway/2.7.x/configure/auth/oidc-curity.md b/app/gateway/2.7.x/configure/auth/oidc-curity.md new file mode 100644 index 000000000000..99d50d2c677d --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/oidc-curity.md @@ -0,0 +1,209 @@ +--- +title: OpenID Connect with Curity +badge: enterprise +--- + +## Phantom Token Integration + +This guide describes how to integrate {{site.ee_product_name}} and the Curity Identity Server using the Kong [OpenID Connect](/hub/kong-inc/openid-connect/) plugin. + +This guide focuses on configuring the plugin for introspection, and especially as it relates to the introspection using the [Phantom Token pattern][curity-phantom-token-pattern]. Some tweaks are made so that a phantom token is provided in the introspection response and then passed on to the upstream API. + +Configuring the Curity Identity Server to provide a Phantom Token in the introspection response is outlined in more detail in this [Introspection and Phantom Tokens][curity-phantom-token-introspection] article. + +### Prerequisites + +* An installation of the [Curity Identity Server][curity-getting-started] +* An introspection endpoint configured with the [Token Procedure Approach][curity-phantom-token-introspection] + +### Configure Kong + +The Kong OpenID Connect plugin is configured to introspect an incoming opaque access token and in return receive a JWT in the introspection response from the Curity Identity Server. The plugin is enabled for a [service or a route][kong-add-service]. + +As part of the introspection, the OpenID Connect plugin also has the ability to validate that required scopes are available in the introspected token. Access to the requested API are denied if the correct scopes are missing. + +If access is granted, the JWT from the introspection response is added to a header and forwarded to the upstream API where it can be consumed. + +#### Create a service + +Create a service that can be used to test the integration. + +```bash +curl -i -X POST http://localhost:8001/services/ \ + --data name="httpbin" \ + --data protocol="http" \ + --data url="https://httpbin.konghq.com" +``` + +#### Create a route + +Add a route to the service. + +```bash +curl -i -X POST http://localhost:8001/services/httpbin/routes \ + --data "paths[]=/httpbin" +``` + +#### Configure the plugin + +The Kong OpenID Connect plugin is enabled for the previously created service. In the example below, the `openid` scope is required in order for access to be granted. As noted by the `config.upstream_headers_claims` configuration, the plugin looks for the `JWT` (the phantom token) claim in the introspection response. The `config.upstream_headers_names` configuration extracts the `JWT` from the introspection response and adds it to a `phantom_token` header in the call to the upstream API. + +```bash +curl -X POST http://localhost:8001/services/httpbin/plugins \ +--data name="openid-connect" \ +--data config.issuer="https://idsvr.example.com/oauth/v2/oauth-anonymous" \ +--data config.client_id="gateway-client" \ +--data config.client_secret="Password1" \ +--data config.scopes_required="openid" \ +--data config.hide_credentials="true" \ +--data config.upstream_access_token_header= \ +--data config.upstream_headers_claims="phantom_token" \ +--data config.upstream_headers_names="phantom_token" \ +--data config.auth_methods="introspection" +``` + +Parameter | Description | Example | Required for integration +--- |--- |--- |--- +`config.issuer` | Used for discovery. Kong appends `/.well-known/openid-configuration`. Should be set to the `realm` or `iss` if no discovery endpoint is available. | `https://idsvr.example.com/oauth/v2/oauth-anonymous` | Yes +`config.client_id` | The ID of a client with the introspection capability | `gateway-client`| Yes +`config.client_secret` | Secret of the client used for introspection| `Password1` | Yes +`config.scopes_required`| Optional scopes required in introspection result for coarse grained authorization. By default the plugin looks for the scopes in the `scopes` claim in the introspection result. This could be overridden with the `config.scopes_claim` configuration. | `openid email records_read` | No +`config.hide_credentials` | Boolean value. This will prevent the incoming Access Token from being forwarded to the upstream API. |`true` | No +`config.upstream_access_token_header` | In order to prevent the plugin from adding the Access Token back in the upstream request, actively set this value to nothing (aka, `nil`) by setting `config.upstream_access_token_header=` as in the example above . This configuration works in conjunction with `config.hide_credentials` to prevent the incoming Access Token from being passed to the upstream API. | `authorization:bearer` | No +`config.upstream_headers_claims` | Contains claim that holds Phantom Token in the introspection result. | `phantom_token` | Yes +`config.upstream_headers_names` | Contains upstream header name that will hold the Phantom Token from the introspection result. | `phantom_token` | Yes +`config.auth_methods` | Several methods are supported for authenticating the request. For this use case, this should be limited to `introspection`. |`introspection` | No +`config.cache_introspection` | Boolean value that controls whether an introspection result should be cached. | `true` | No +`config.introspect_jwt_tokens` | Boolean value that controls if JWTs sent in an Authorization header should also be introspected. | `false` | No +`config.introspection_endpoint` | Endpoint for introspection. Might be needed if discovery is not possible. | `https://idsvr.example.com/oauth/v2/oauth-introspect` | No + +### Test the configuration + +Any supported OAuth/OIDC flow can be used to obtain an opaque access token from the Curity Identity Server. Several approaches for obtaining a token are outlined in the [Curity Getting Started Guide][curity-getting-started]. Make sure that the token issued contains the `openid` scope. + +Call the exposed service created earlier and pass the opaque access token in the `Authorization` header. + +```bash +curl -X GET http://kong:8000/httpbin/get \ +--header "Authorization: Bearer /auth`). + +{:.note} +> **NOTE:** There is an issue with short-lived access tokens that is under investigation. Increase the `Access Token Time to Live` in the client configuration to `3000` as a temporary workaround. + +More information is available in the [Code Flow][curity-code-flow-tutorial] tutorial. + +### Configure OpenID Connect in the Kong Developer Portal + +Enabling the Kong Developer Portal is outlined in the [Kong Dev Portal Documentation][kong-dev-portal-doc] and not covered in this article. The documentation also covers how to configure the [OpenID Connect Plugin][kong-dev-portal-doc-oidc]. + +#### Example Configuration Object + +Below is an example configuration object that is used to configure the OIDC plugin for the Dev Portal. + +```json +{ + "redirect_uri": ["https://kong-dev-portal:8004/default/auth"], + "consumer_by": ["username","custom_id","id"], + "leeway": 1000, + "scopes": ["openid","profile","email"], + "logout_query_arg": "logout", + "login_redirect_uri": ["https://kong-dev-portal:8003"], + "login_action": "redirect", + "logout_redirect_uri": ["https://kong-dev-portal:8003"], + "ssl_verify": false, + "client_id": ["kong-dev-portal-client"], + "forbidden_redirect_uri": ["https://kong-dev-portal:8003/unauthorized"], + "client_secret": ["Pa$$w0rd!"], + "issuer": "https://idsvr.example.com/oauth/v2/oauth-anonymous/", + "logout_methods": ["GET"], + "consumer_claim": ["email"], + "login_redirect_mode": "query" +} +``` + +### Curity Authentication Action + +An Authentication Action to automatically provision the user to the Kong Developer Portal is available in the Curity GitHub repository. Using the Action is not mandatory as the user could be provisioned in other ways, such as manually through the Kong Developer portal login page. However, using the Authentication Action would streamline the user flow since the Action takes the user's full name and the email from the Curity Authenticator and automatically provision that to the Kong Developer Portal using the exposed API. + +The [Kong Developer Portal User Provisioner][curity-kong-dev-portal-user-provisioner] action is available as open source and can be forked to fit the needs of the environment as needed. + +#### Configuration + +This Action is straightforward to configure. An HTTP Client is needed to communicate with the Kong Dev Portal API. By default, the **HTTP Authentication** can be left out. Only a correct scheme needs to be configured (HTTP or HTTPS). + +The Action also configures the URL to the registration endpoint of the Kong Developer Portal. Here the scheme needs to match what's configured in the HTTP Client used. + +When the action is created, it can be assigned to the Authenticators used in the client configured in the Curity Identity Server as described above. + +#### Action to Resolve Additional User Information + +Depending on the Authenticator used, an additional Action may be needed to resolve additional information. By default, The Kong Developer portal provisioning requires `Full Name` and `email`. If the Authenticator does not provide this, it's possible to use an Action to resolve the data. This could be as simple as a **Data Source** action configured to use a Data Source that provides the information. + +![Chain Actions](/assets/images/products/gateway/dev-portal/authentication-and-actions.png) + +By default, the Kong Developer Portal Provisioner Action works on the default account table schema of the Curity Identity Server database. This provides `email` as a column, but the `Full Name` is not readily available. The Action operates on the `attributes` column and parse the information to pass the user's Full Name to the Kong Dev Portal. + +The attributes column contains this structure: + +```json +{"emails":[{"value":"alice@example.com","primary":true}],"phoneNumbers":[{"value":"555-123-1234","primary":true}],"name":{"givenName":"alice","familyName":"anderson"},"agreeToTerms":"on","urn:se:curity:scim:2.0:Devices":[]} +``` + +The data source used to resolve additional information needs to be configured with an appropriate **Attribute Query**. This would look similar to this: + +```sql +select * from "accounts" where "username"= :subject +``` + +### Conclusion + +With relatively simple configurations in both the Curity Identity Server and the Kong Developer Portal, it's possible to leverage Curity as the Identity Provider for the Kong Dev Portal. This provides a very seamless flow for user authentication to the Kong Dev Portal. With the added capability of an Authentication Action, it is possible to automatically provision the user to the Kong Dev Portal for an even more streamlined experience. + +[kong-add-service]: /gateway/{{page.release}}/admin-api/#service-object +[curity-phantom-token-introspection]: https://curity.io/resources/learn/introspect-with-phantom-token +[curity-getting-started]: https://curity.io/resources/getting-started +[curity-phantom-token-pattern]: https://curity.io/resources/learn/phantom-token-pattern +[curity-code-flow-tutorial]: https://curity.io/resources/learn/code-flow +[curity-kong-dev-portal-user-provisioner]: https://curity.io/resources/learn/provision-kong-dev-portal-user +[kong-dev-portal-doc]: /gateway/{{page.release}}/developer-portal +[kong-dev-portal-doc-oidc]: /gateway/{{page.release}}/developer-portal/configuration/authentication/oidc diff --git a/app/gateway/2.7.x/configure/auth/oidc-google.md b/app/gateway/2.7.x/configure/auth/oidc-google.md new file mode 100644 index 000000000000..da98b123772d --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/oidc-google.md @@ -0,0 +1,67 @@ +--- +title: OpenID Connect with Google +badge: enterprise +--- + +This guide covers an example OpenID Connect plugin configuration to authenticate browser clients using Google's identity provider. + +## Prerequisites + +Because OpenID Connect deals with user credentials, all transactions should take place over HTTPS. Although user passwords for third party identity providers are only submitted to those providers and not Kong, authentication tokens do grant access to a subset of user account data and protected APIs, and should be secured. As such, you should make Kong's proxy available via a fully-qualified domain name and [add a certificate][add-certificate] for it. + +## Google IDP Configuration + +Before configuring Kong, you'll need to set up a Google APIs project and create a credential set. Following [Google's instructions][google-oidc], [create a new set of OAuth client ID credentials][google-create-credentials] with the Web application class. Add an authorized redirect URI for part of the API you wish to protect (more complex applications may redirect to a resource that sets additional +application-specific state on the client, but for our purposes, any protected URI will work). Authorized JavaScript origins can be left blank. + +You can optionally customize the consent screen to inform clients who/what application is requesting authentication, but this is not required for testing. All steps after can be ignored, as Kong handles the server-side authentication request and token validation. + +## Kong Configuration + +If you have not yet [added a **Service**][add-service], go ahead and do so. Again, note that you should be able to secure this Service with HTTPS, so if you are configuring a host, use a hostname you have a certificate for. + +### Basic Plugin Configuration + +Add a plugin with the configuration below to your Service using an HTTP client or Kong Manager. Make sure to use the same redirect URI as configured earlier: + +```bash +curl -i -X POST http://localhost:8001/services/{SERVICE_NAME}/plugins \ + --data name="openid-connect" \ + --data config.issuer="https://accounts.google.com/.well-known/openid-configuration" \ + --data config.client_id="YOUR_CLIENT_ID" \ + --data config.client_secret="YOUR_CLIENT_SECRET" \ + --data config.redirect_uri="https://example.com/api" \ + --data config.scopes="openid,email" +``` + +Visiting a URL matched by that Service in a browser will now redirect to Google's authentication site and return you to the redirect URI after authenticating. You'll note, however, that we did not configure anything to map authentication to consumers and that no consumer is associated with the subsequent request. Indeed, if you have configured other plugins that rely on consumer information, such as the ACL plugin, you will not have access. At present, the plugin configuration confirms that +users have a Google account, but doesn't do anything with that information. + +Depending on your needs, it may not be necessary to associate clients with a consumer. You can, for example, configure the `domains` parameter to limit access to a internal users if you have a G Suite hosted domain, or configure `upstream_headers_claims` to send information about the user upstream (e.g. their email, a profile picture, their name, etc.) for use in your applications or for analytics. + +### Consumer Mapping + +If you need to interact with other Kong plugins using consumer information, you must add configuration that maps account data received from the identity provider to a Kong consumer. For this example, we'll map the user's Google account email by setting a `custom_id` on their consumer, e.g. + +```bash +curl -i -X POST http://localhost:8001/consumers/ \ + --data username="Yoda" \ + --data custom_id="user@example.com" + +curl -i -X PATCH http://localhost:8001/services/{SERVICE_NAME}/plugins/{OIDC_PLUGIN_ID} \ + --data config.consumer_by="custom_id" \ + --data config.consumer_claim="email" +``` + +Now, if a user logs into a Google account with the email `user@example.com`, Kong will apply configuration associated with the consumer `Yoda` to their requests. Note that while Google provides account emails, not all identity providers will. OpenID Connect does not have many required claims--the [only required user identity claim][oidc-id-token] is `sub`, a unique subscriber ID. Many optional claims [are +standardized][oidc-standard-claims], however--if a provider returns an `email` claim, the contents will always be an email address. + +This also requires that clients login using an account mapped to some consumer, which may not be desirable (e.g. you apply OpenID Connect to a service, but only use plugins requiring a consumer on some routes). To deal with this, you can set the `anonymous` parameter in your OIDC plugin configuration to the ID of a generic consumer, which will then be used for all authenticated users that cannot be mapped to some other consumer. + + +[add-certificate]: /gateway/{{page.release}}/admin-api/#add-certificate +[google-oidc]: https://developers.google.com/identity/protocols/OpenIDConnect +[google-create-credentials]: https://console.developers.google.com/apis/credentials +[add-service]: /gateway/{{page.release}}/admin-api/#service-object +[oidc-id-token]: http://openid.net/specs/openid-connect-core-1_0.html#IDToken +[oidc-standard-claims]: http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims diff --git a/app/gateway/2.7.x/configure/auth/oidc-okta.md b/app/gateway/2.7.x/configure/auth/oidc-okta.md new file mode 100644 index 000000000000..92c5ba0c339b --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/oidc-okta.md @@ -0,0 +1,256 @@ +--- +title: OpenID Connect with Okta +badge: enterprise +--- + +This guide covers an example OpenID Connect plugin configuration to authenticate browser clients using an Okta identity provider. + +For information about configuring OIDC using Okta as an Identity provider +in conjunction with the Application Registration plugin, see +[Set Up External Portal Application Authentication with Okta and OIDC](/gateway/{{page.release}}/developer-portal/administration/application-registration/okta-config). + +## Authorization code flow with the OpenID Connect plugin and Okta + +### Sign-in flow + +![OIDC sign-in flow](/assets/images/products/plugins/openid-connect/OIDCsignin.png) + +1. If the client does not have a session cookie, it initiates sign in with Kong. +2. Kong responds to the client with an **authorization cookie** and a location to redirect (with Okta as the header). +3. the client redirects to Okta so the user can sign in. +4. Okta responds with an **authorization code** and a location to redirect (with Kong as the header). + +At this point, the client has successfully signed in and has an **authorization code** (from Okta) and an **authorization cookie** (from Kong). + +### Access flow + +![OIDC access flow](/assets/images/products/plugins/openid-connect/OIDCaccess.png) + +1. The client redirects to Kong and automatically sends the **authorization code** (from Okta) and an **authorization cookie** (from Kong). +2. Kong verifies the **authorization code** with Okta. +3. Okta sends and **access token** and **ID token** to Kong. +4. Kong proxies the client request with the **access token** from Okta. +5. Kong receives a service response. +6. Kong sends the service response to the client, along with a **session cookie** for future access. + +At this point, the client now has a **session** with Kong that allows mediated access to the service. + +### Session flow + +![OIDC session flow](/assets/images/products/plugins/openid-connect/OIDCsession.png) + +1. The client sends requests with a **session cookie**. +2. Kong matches the session cookie to the associate **access token** and proxies the request. +3. Kong gets a response from the service. +4. Kong sends the response to the client. + +Kong’s session with the client ensures that the client does not need to make constant requests to Okta. The duration of the session can be configured. + +## Example of configuring the OIDC plugin with Okta + +### Prerequisites + +The steps in the guide offer an example of configuring OIDC with Okta on a specific route. To follow this guide, you need the following: + +* A [developer account](https://developer.okta.com) with Okta. +* A running version of {{site.base_gateway}}. +* Access to the [OpenID Connect plugin](/hub/kong-inc/openid-connect/). +* A [service](/gateway/{{page.release}}/admin-api/#service-object) +and [route](/gateway/{{page.release}}/admin-api/#route-object) in +{{site.base_gateway}} whose access you want to protect with Okta. For this +guide, assume the route is in the default workspace. +* If using {{site.base_gateway}} locally, you need Internet access. +* Any network access control to your Kong node must allow traffic to and from Okta, the upstream service, and the client. + + For security reasons, make sure all requests are sent over HTTPS, and make the Kong proxy available + with a fully-qualified domain name and [properly configured certificate](/gateway/{{page.release}}/admin-api/#certificate-object). + Authorization tokens should also be stored securely. + +### Configure Okta + +1. [Register](https://developer.okta.com/docs/guides/add-an-external-idp/openidconnect/register-app-in-okta/) the application you are using Kong to proxy. +1. From the left menu, select **Applications**, then **Create App Integration**. +1. Select the application type: + + 1. Under **Sign-in method**, select **OIDC - OpenID Connect**. + 1. Under **Application Type**, select **Web Application**. + +1. Select **Next**. Configure the application: + 1. Create a unique name for your application. + 1. Under **Grant Type**, select **Authorization Code**. + 1. In both the **Sign-in redirect URIs** and + **Sign-out redirect URIs** fields, enter a location handled by your Route + in {{site.base_gateway}}. + + For this example, you can enter `https://kong.com/api`. + + 1. In the Assignments section, for **Controlled access**, choose your + preferred access level for this application. This preferred access level sets the permissions for + Okta admins. + +1. Save your settings to generate connection details. + + Leave this page open. You'll need the details here to configure the Kong OIDC plugin. + +1. Add an Authorization Server. From the left sidebar, go to +**Security > API > Authorization Server** and create a server named + **Kong API Management** with an audience and description. Click **Save**. + + On the page that appears, note the **Issuer** address. You need this address + to configure the Kong OIDC Plugin. + +### Configure the OIDC plugin in {{site.base_gateway}} + +#### Minimum configuration requirements + +Configure the following parameters: + +* `issuer`: The issuer `url` from which OpenID Connect configuration can be discovered. Using Okta, specify the domain and server in the path: + * `https://YOUR_OKTA_DOMAIN/oauth2/YOUR_AUTH_SERVER/.well-known/openid-configuration` +* `auth_method`: A list of authentication methods to use with the plugin, such as passwords, introspection tokens, etc. The majority of cases use `authorization_code`, and {{site.base_gateway}} will accept all methods if no methods are specified. +* `client_id`: The `client_id` of the OpenID Connect client registered in OpenID Connect Provider. Okta provides one to identify itself. +* `client_secret`: The `client_secret` of the OpenID Connect client registered in OpenID Connect Provider. These credentials should never be publicly exposed. +* `redirect_uri`: The `redirect_uri` of the client defined with `client_id` (also used as a redirection URI for the authorization code flow). +* `scopes`: The scope of what OpenID Connect checks. `openid` by default; set to `email` and `profile` for this example. + +{% navtabs %} +{% navtab Configure plugin with Kong Manager %} + +1. In Kong Manager, from the Workspaces tab, select the workspace where your +route is configured. + +1. Click **Routes** in the left navigation. + +1. On the Routes page, select the route you have configured to protect with +Okta and click **View**. + +1. Scroll to the bottom of the page and click **Add Plugin**. + +1. Select the **OpenID Connect** plugin. + +1. On the plugin's configuration, in the **Common** tab, configure the +following, at minimum: + + 1. **Issuer (Discovery Document URI)**: + + ``` + https://{YOUR_OKTA_DOMAIN}/oauth2/{YOUR_AUTH_SERVER}/.well-known/openid-configuration + ``` + + The `issuer` URL can be found in your Authorization Server settings. + + 1. **Client ID**: `{YOUR_CLIENT_ID}` + + Replace `YOUR_CLIENT_ID` with the client ID shown in your Okta + application's **General** page. + + 1. **Client Secret**: `{YOUR_CLIENT_SECRET}` + + Replace `YOUR_CLIENT_SECRET` with the client secret shown in your Okta + application's **General** page. + + 1. **Auth Methods**: `Authorization code flow` + + This parameter lists of all the authentication methods + that you want the plugin to accept. If you don't select an auth method, + all auth methods are allowed by default. + +1. Switch to the **Authorization** tab and fill out **config.scopes required** with +`openid, email, profile`. + +1. Switch to the **Advanced** tab and fill out **config.redirect_uri** with + `https://kong.com/api`. + + The `redirect_uri` should be the URI you specified earlier when configuring + your app. + +1. Click **Create** to save and apply the plugin to the Route. + +For a list of all available configuration parameters and what they do, see the +[OIDC plugin reference](/hub/kong-inc/openid-connect). + +{% endnavtab %} +{% navtab Configure plugin with Admin API %} + +Configure the OpenID Connect plugin using the following sample values: + +```bash +$ curl -i -X POST https://KONG_ADMIN_URL/routes/ROUTE_ID/plugins + --data name="openid-connect" \ + --data config.issuer="https://YOUR_OKTA_DOMAIN/oauth2/YOUR_AUTH_SERVER/.well-known/openid-configuration" \ + --data config.client_id="YOUR_CLIENT_ID" \ + --data config.client_secret="YOUR_CLIENT_SECRET" \ + --data config.redirect_uri="https://kong.com/api" \ + --data config.scopes="openid" \ + --data config.scopes="email" \ + --data config.scopes="profile" +``` + +For a list of all available configuration parameters and what they do, see the +[OIDC plugin reference](/hub/kong-inc/openid-connect). + +{% endnavtab %} +{% endnavtabs %} + +Visiting a URL matched by that route in a browser will now redirect to Okta's authentication +site and return you to the redirect URI after authenticating. + +### Test Your Configuration + +Test the following conditions to ensure a successful integration of the OIDC plugin with Okta: + +* Unauthorized access to a route is blocked +* Authorized access is allowed after login/providing first set of credentials + * Ensure the identity is registered with the IdP + * Steps for debugging +* Authorized access is allowed on immediate subsequent attempts + * Perhaps highlight where the cookie is stored +* Previously authorized access is no longer allowed after cookie terminates + * Set a very short TTL on the session to ensure the tester doesn’t need to wait long to get locked out + +### Access Restrictions + +The example configuration allows users to authenticate and access the Route even though +no Consumer was created for them. Any user with a valid account in the directory +will have access to the Route. The OIDC plugin allows this as the simplest authentication option, +but you may wish to restrict access further. There are several options for this: + +- Consumer Mapping +- Pseudo-Consumer Mapping + +#### Consumer Mapping + +If you need to interact with other Kong plugins using consumer information, you +can add configuration that maps account data received from the identity provider to a Kong consumer. +For this example, the user's Okta's AD account GUID is mapped to a Consumer by setting it +as the `custom_id` on their consumer: + +```bash +$ curl -i -X POST http://admin.kong.example/consumers/ \ + --data username="Yoda" \ + --data custom_id="e5634b31-d67f-4661-a6fb-b6cb77849bcf" + +$ curl -i -X PATCH http://admin.kong.example/plugins/OIDC_PLUGIN_ID \ + --data config.consumer_by="custom_id" \ + --data config.consumer_claim="sub" +``` + +Now, if a user logs into an Okta account with the GUID `e5634b31-d67f-4661-a6fb-b6cb77849bcf`, Kong will apply configuration associated with the Consumer `Yoda` to their requests. + +This also requires that clients login using an account mapped to some Consumer, which might +not be desirable (e.g., you apply OpenID Connect to a service, but only use plugins +requiring a Consumer on some Routes). To deal with this, you can set the `anonymous` parameter +in your OIDC plugin configuration to the ID of a generic Consumer, which will +then be used for all authenticated users that cannot be mapped to some other Consumer. +You can alternately set `consumer_optional` to `true` to allow similar logins +without mapping an anonymous Consumer. + +#### Pseudo-consumers + +For plugins that typically require consumers, the OIDC plugin can provide a consumer ID based on the value of a claim without mapping to an actual Consumer. Setting `credential_claim` to a claim [in your plugin configuration][credential-claim] will extract the value of that claim and use it where Kong would normally use a consumer ID. Note that this may not work with all consumer-related functionality. + +Similarly, setting `authenticated_groups_claim` will extract that claim's value and use it as a group for the ACL plugin. + +[okta-authorization-server]: https://developer.okta.com/docs/guides/customize-authz-server/create-authz-server/ +[okta-register-app]: https://developer.okta.com/docs/guides/add-an-external-idp/openidconnect/register-app-in-okta/ +[credential-claim]: /hub/kong-inc/openid-connect/#configcredential_claim diff --git a/app/gateway/2.7.x/configure/auth/oidc-use-case.md b/app/gateway/2.7.x/configure/auth/oidc-use-case.md new file mode 100644 index 000000000000..e0bc6cc41604 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/oidc-use-case.md @@ -0,0 +1,34 @@ +--- +title: OpenID Connect +badge: enterprise +--- + +## What does OpenID Connect do? + +OpenID Connect provides a way to form a *federation* with *identity providers*. Identity providers are third parties that store account credentials. If the identity provider authenticates a user, the application trusts that provider and allows access to the user. The *identity provider* bears some responsibility for protecting the user’s credentials and ensuring authenticity, so applications no longer need to on their own. + +Besides delegating responsibility to an identity provider, OpenID Connect also makes single sign-on possible without storing any credentials on a user’s local machine. + +Finally, enterprises may want to manage access control for many applications from one central system of record. For example, they may want employees to be able to access many different applications using their email address and password. They may want to also change access (e.g. if an employee separates or changes roles) from one central point. OpenID Connect addresses this challenge by providing a way for many different applications to authenticate users through the same third-party identity provider. + +## What does Kong’s OpenID Connect plugin do? + +Just as OpenID Connect enables developers to offload authentication to another party, Kong enables developers to separate entire processes from their applications. Rather than needing to hand write the code for OpenID Connect *within* a service, developers can place Kong in front of the service and have Kong handle authentication. This separation allows developers to focus on the business logic within their application. It also allows them to easily swap out services while preserving authentication at the front door, and to effortlessly spread the same authentication to *new* services. + +Kong users may prefer OpenID Connect to other authentication types, such as Key Auth and Basic Auth, because they will not need to manage the database storing passwords. Instead, they can offload the task to a trusted identity provider of their choice. + +While the OpenID Connect Plugin can suit many different use cases and extends to other Plugins such as JWT (JSON Web Token) and 0Auth 2.0, the most common use case is the Authorization Code flow. + +## References +See our series of integration guides to configure the OIDC plugin for your +identity provider: + + - [Auth0](/gateway/{{page.release}}/configure/auth/oidc-auth0/) + - [Amazon AWS Cognito](/gateway/{{page.release}}/configure/auth/oidc-cognito/) + - [Curity](/gateway/{{page.release}}/configure/auth/oidc-curity/) + - [Google](/gateway/{{page.release}}/configure/auth/oidc-google/) + - [Microsoft Azure Active Directory (Azure AD)](/gateway/{{page.release}}/configure/auth/oidc-azuread/) + - [Okta](/gateway/{{page.release}}/configure/auth/oidc-okta/) + + For a full list of tested providers and all available configuration options, + see the [OpenID Connect plugin reference](/hub/kong-inc/openid-connect/). diff --git a/app/gateway/2.7.x/configure/auth/rbac/add-admin.md b/app/gateway/2.7.x/configure/auth/rbac/add-admin.md new file mode 100644 index 000000000000..4c6d1110a166 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/rbac/add-admin.md @@ -0,0 +1,89 @@ +--- +title: Invite an Admin +badge: enterprise +--- + +An Admin is any user in Kong Manager. They may access +Kong entities within their assigned Workspaces based +on the Permissions of their Roles. + +This guide describes how to invite an Admin in Kong +Manager. As an alternative, if a Super Admin wants to +invite an Admin with the Admin API, it is possible to +do so using +[`/admins`](/gateway/{{page.release}}/admin-api/admins/reference/#invite-an-admin). + +## Invite an Admin + +1. Navigate to the **Teams** page in Kong Manager + +2. From the **Admins** tab select **Invite Admin** + +3. Fill out the username and email address. When a new **Admin** receives an +invitation, they will only be able to log in with that email address. Assign the appropriate **Role** and click **Invite User** to send the invitation. + + **Super Admins** can invite users to multiple **Workspaces**, and + assign them any **Role** available within **Workspaces**, including **Roles** that exist by default (e.g. `super-admin`, `read-only`) and **Roles** with customized permissions. + + The **Super Admin** can see all available roles across + **Workspaces** on the **Roles** tab of the **Organization** page. + + +4. On the **Teams** page, the new invitee will appear on the **Admins** list with the under **Invited**. Once they accept the invitation, the user will be listed in the main **Admins** list. + + By default, the registration link will expire after 259,200 + seconds (3 days). This time frame can be configured with the `kong.conf` + file in `admin_invitation_expiry`. + + If an email fails to send, either due to an incorrect email + address or an external error, it will be possible to resend an invitation. + + If SMTP is not enabled or the invitation email fails to send, + it is possible for the Super Admin to copy and provide a registration link + directly. + +5. The newly invited **Admin** will have the ability to set a password. If the **Admin** ever forgets the password, it is possible for them to reset it through a recovery email. + + +## Copy and Send a Registration Link + +If a mail server is not yet set up, it is still possible to invite Admins to register and log in. + +1. Invite an **Admin** as described in the section above. + +2. If the "View" link is clicked next to the invited Admin's name, a + `register_url` is displayed on the invitee's details page. + +3. Copy and directly send this link to the invited Admin so that they may set + up their credentials and log in. + +If `admin_gui_auth` is `ldap-auth-advanced`, credentials are not stored in Kong, and the Admin will be directed to log in. + +## How to Grant an Admin Access with LDAP + +1. Pick a user in the LDAP Directory that will be the Super Admin. + +2. Change the Super Admin’s username in Kong by making a `PATCH` request to +`admins/kong_admin` and setting the value of `username` to the corresponding +LDAP `attribute`. + +For example, if the LDAP user's attribute is `einstein`, +the `PATCH` to `/admins/kong_admin` should have a `username` set to `einstein`. + +3. Log in to Kong Manager using the LDAP credentials associated with the Super +Admin. + +4. Invite Admins from the "Admins" page in Kong Manager, ensuring that the +`username` of each Admin is mapped to the `attribute` value set in the LDAP +directory. + + To enable the Admins to log in, it is still necessary + to assign a Role to them. + +5. Once an Admin has logged in successfully and accesses the Admin API using +their LDAP credentials, they will be marked as “approved” on the "Admins" list +in Kong Manager + + The new Admins will still receive an email, but all + credentials will be handled through the LDAP server, not Kong Manager + or the Admin API. diff --git a/app/gateway/2.7.x/configure/auth/rbac/add-role.md b/app/gateway/2.7.x/configure/auth/rbac/add-role.md new file mode 100644 index 000000000000..75ceaff25bbc --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/rbac/add-role.md @@ -0,0 +1,61 @@ +--- +title: Add a Role and Permissions +badge: enterprise +--- + +Roles make it easy to logically group and apply the same +set of Permissions to Admins. Permissions may be +customized in detail, down to individual actions and endpoints. + +{{site.base_gateway}} includes default Roles for standard +use cases, e.g. inviting additional Super Admins, +inviting Admins that may only `read` endpoints. + +This guide describes how to create a custom Role in Kong +Manager for a unique use case. As an alternative, if a +Super Admin wants to create a Role with the Admin API, +it is possible to do so using +[`/rbac/roles`](/gateway/{{page.release}}/admin-api/rbac/reference/#add-a-role). +To add Permissions to the new Role, use +[`/rbac/roles/{name_or_id}/endpoints`](/gateway/{{page.release}}/admin-api/rbac/reference/#add-a-role-endpoint-permission) +for endpoints or +[`/rbac/roles/{name_or_id}/entities`](/gateway/{{page.release}}/admin-api/rbac/reference/#add-a-role-entity-permission) +for specific entities. + +## Prerequisites + +* [`enforce_rbac = on`](/gateway/{{page.release}}/reference/configuration/#enforce_rbac) +* {{site.base_gateway}} has [started](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/) +* Logged in to Kong Manager as a **Super Admin** + +## Add a role and permissions + +1. On the **Admins** page, to create a new **Role**, click the +**Add Role** button at the top right of the list of **Roles**. + +1. On the **Add Role** form, name the **Role** according to the +**Permissions** you want to grant. + + ![New Role naming](https://konghq.com/wp-content/uploads/2018/11/km-new-role.png) + + **Note:** It may be helpful for future reference to include + a brief comment describing the reason for the **Permissions** or + a summary of the **Role**. + +1. Click the **Add Permissions** button and fill out the form. Add the endpoint **Permissions** by marking the appropriate checkbox. + + ![New Role permissions](https://konghq.com/wp-content/uploads/2018/11/km-perms.png) + +1. Click **Add Permission to Role** to see the permissions listed on the form. + + ![New Role permissions list](https://konghq.com/wp-content/uploads/2018/11/km-perms-list.png) + +1. To forbid access to certain endpoints, click **Add Permission** +again and use the **negative** checkbox. + + ![Negative permissions](https://konghq.com/wp-content/uploads/2018/11/km-negative-perms.png) + +1. Submit the form and see the new **Role** appear on the +**Admins** page. + + ![Roles list](https://konghq.com/wp-content/uploads/2018/11/km-roles-list.png) diff --git a/app/gateway/2.7.x/configure/auth/rbac/add-user.md b/app/gateway/2.7.x/configure/auth/rbac/add-user.md new file mode 100644 index 000000000000..620ce980bd5a --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/rbac/add-user.md @@ -0,0 +1,60 @@ +--- +title: Create an RBAC User +badge: enterprise +--- + +## Admins vs. RBAC Users + +| | Admin API | Kong Manager | +|------------|-----------|--------------| +| Admins | ✔️ | ✔️ | +| RBAC Users | ✔️ | X | + + +An RBAC User has the ability to access the {{site.base_gateway}} Admin API. The Permissions assigned to their Role will define the types of actions they can perform with various Admin API objects. + +An [Admin](/gateway/{{page.release}}/configure/auth/kong-manager/), like an RBAC User, has the ability to access the {{site.base_gateway}} Admin API. The Admin also has the ability log in to Kong Manager. Like an RBAC User, an Admin’s Role will determine the types of actions it can perform—except that they will also have the ability to benefit from Kong Manager’s interface and visualizations. + +If creating a *service account* for {{site.base_gateway}}, e.g., for a machine as part of an automated process, then an RBAC User is adequate. + +If creating a *personal account* for {{site.base_gateway}}, then Admin may be preferable since it also has access to Kong Manager. + +## Prerequisites + +* Authentication and RBAC are [enabled](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/) +* [Logged in as the Super Admin](/gateway/{{page.release}}/plan-and-deploy/security/start-kong-securely/) +or a user that has `/admins` and `/rbac` read and write access. + +## How to Add an RBAC User in Kong Manager + +1. From the dashboard, click the **Teams** tab in the top navigation menu. + +2. On the **Teams** page, click the **RBAC Users** tab. + +3. Using the dropdown menu, select which **Workspace** the new user has access to. + + >Note: The **Default Workspace** is global, meaning the RBAC User with access to default has access to entities across all other Workspaces. This Workspace assignment is useful for administrative and auditing accounts, but not for members of specific teams. + +4. Click the **Add New User** button to the right of the dropdown menu to open the registration form. + +5. In the **Add New User** registration form provide a Name, User Token, Comment, and Enablement + + The name of the RBAC User must be globally unique, even if two users are in different Workspaces, and it cannot have the same as an Admin account. + + These naming conventions are important if using OIDC, LDAP, or another external method of identity and access management. + + The RBAC User account is enabled by default, if you want the RBAC User account to start in a disabled state and enable it later, uncheck the box. + +6. Click the **Add User Roles** button in the **Role(s) per workspace** section. Select the Role (or Roles) desired for the new RBAC User. + + If the RBAC User has no Roles assigned, it will not have permission to access any objects. + + An RBAC User’s Role assignments may be altered later if needed. + + The Roles can only belong to one Workspace, as selected in Step 3. + + To provide an RBAC User with access to objects in multiple Workspaces, see Step 3. + +7. Click **Create User** to complete the user registration. + + The page will automatically redirect back to the **Teams** page, where the new user is listed. diff --git a/app/gateway/2.7.x/configure/auth/rbac/index.md b/app/gateway/2.7.x/configure/auth/rbac/index.md new file mode 100644 index 000000000000..3ba7179b0f2a --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/rbac/index.md @@ -0,0 +1,82 @@ +--- +title: RBAC in Kong Manager +badge: enterprise +--- + +In addition to authenticating Admins and segmenting Workspaces, +{{site.base_gateway}} has the ability to enforce Role-Based Access Control +(RBAC) for all resources with the use of Roles assigned to Admins. + +As the Super Admin (or any Role with read and write +access to the `/admins` and `/rbac` endpoints), it is possible to +create new Roles and customize Permissions. + +In Kong Manager, RBAC affects how Admins are able to navigate +through the application. + +### Default Roles + +Kong includes Role-Based Access Control (RBAC). Every Admin using Kong Manager +will need an assigned Role based on the resources they have Permission to access. + +When a Super Admin starts Kong for the first time, the `default` Workspace will +include three default Roles: `read-only`, `admin`, and `super-admin`. The three +Roles have Permissions related to every Workspace in the cluster. + +Similarly, if a Role is confined to certain Workspaces, the Admin assigned to it +will not be able to see either the overview or links to other Workspaces. + +If a Role does not have Permission to access entire endpoints, +the Admin assigned to the Role will not be able to see the related navigation links. + +{:.important} +> Important: Although a default Admin has full permissions with every +endpoint in Kong, only a Super Admin has the ability to assign and modify RBAC Permissions. An Admin is not able to modify their own Permissions or delimit a Super Admin's Permissions. + +### RBAC in Workspaces + +RBAC Roles and Permissions will be specific to a Workspace if they are assigned +from within one. For example, if there are two Workspaces, Payments and +Deliveries, an Admin created in Payments will not have access to any +endpoints in Deliveries. + +When a Super Admin creates a new Workspace, there are three default Roles that +mirror the cluster-level Roles, and a fourth unique to each Workspace: +`workspace-read-only`, `workspace-admin`, `workspace-super-admin`, and +`workspace-portal-admin`. + +These roles can be viewed in the **Teams > Roles** tab in Kong Manager. + + +{:.important} +> **Important:** Any role assigned in the `default` workspace has permissions to all subsequently created +> workspaces unless roles in specific workspaces are explicitly assigned. When roles across multiple workspaces are +> assigned, roles in workspaces other than `default` take precedent. For example, a super admin assigned to the +> `super-admin` role in the `default` workspace as well as the `workspace-read-only` role in the `ws` workspace has RBAC permissions across all workspaces +> and full permissions to endpoints in workspaces except the `ws` workspace. The admin only has read-only permissions to endpoints in the `ws` workspace. + +### How RBAC rules work in {{site.base_gateway}} + +Although there are concepts like groups and roles in {{site.base_gateway}}, when determining if a user has sufficient permissions to access the endpoint, combinations of workspace and endpoint are collected from roles and groups assigned to a user, being the minimal unit for {{site.base_gateway}} to check for permissions. These combinations will be referred to as “rules” in the following paragraphs. + +{{site.base_gateway}} uses a precedence model, from most specificity to least specificity, to determine if a user has access to an endpoint. For each request {{site.base_gateway}} checks for an RBAC rule assigned to the requesting user in the following order: + +* An allow or deny rule against the current endpoint in the current workspace + +* An allow or deny rule against the current endpoint in any workspace (`*`) + +* An allow or deny rule against any endpoint (`*`) in the current workspace + +* An allow or deny rule against any endpoint (`*`) in any workspace (`*`) + +If {{site.base_gateway}} finds a matching rule for the current user, endpoint, and workspace it allows or denies the request according to +that rule. Once {{site.base_gateway}} finds an applicable rule, it stops, and does not continue checking for less specific rules. If no rules are found, the request is denied. + +The default admin roles define permissions for any workspace is (`*`). +{{site.base_gateway}} stops at the first role, which means any role assigned in the default workspace has permissions to all subsequently created workspaces unless roles +in specific workspaces are explicitly assigned. When roles across multiple workspaces are assigned, roles in workspaces +other than default take precedent. For example, a user assigned to the `super-admin` role in the default workspace as well +as the `workspace-read-only` role in the `ws` workspace has full permissions to endpoints in all workspaces except the `ws` workspace. The user only has read-only permissions to endpoints in the `ws` workspace. + +{{site.base_gateway}} allows you to add negative rules to a role. A negative rule denies actions associated with the endpoint. +Meanwhile, a negative rule precedes other non-negative rules while following the above rules. \ No newline at end of file diff --git a/app/gateway/2.7.x/configure/auth/service-directory-mapping.md b/app/gateway/2.7.x/configure/auth/service-directory-mapping.md new file mode 100644 index 000000000000..8ae723821d52 --- /dev/null +++ b/app/gateway/2.7.x/configure/auth/service-directory-mapping.md @@ -0,0 +1,162 @@ +--- +title: Mapping LDAP Service Directory Groups to Kong Roles +badge: enterprise +--- + +Service Directory Mapping allows organizations to use their LDAP Directory for authentication and authorization in {{site.base_gateway}}. + +After starting {{site.base_gateway}} with the desired configuration, you can create new Admins whose usernames match those in your LDAP directory. Those users will then be able to accept invitations to join Kong Manager and log in with their LDAP credentials. + +How Service Directory Mapping works in Kong: +* Roles are created in {{site.base_gateway}} using the Admin API or Kong Manager. +* Groups are created and roles are associated with the groups. +* When users log in to Kong Manager, they get permissions based on the group(s) they belong to. + +For example, if a User's Group changes in the Service Directory, their Kong Admin account's associated Role also changes in {{site.base_gateway}} the next time they log in to Kong Manager. The mapping removes the task of manually managing access in {{site.base_gateway}}, as it makes the Service Directory the system of record. + +## Prerequisites + +* {{site.base_gateway}} installed and configured +* Kong Manager access +* A local LDAP directory + +## Configure Service Directory Mapping + +Configure Service Directory Mapping to use your LDAP Directory for authentication and authorization. + +## Start {{site.base_gateway}} + +From a terminal window, enter: + +``` +$ kong start [-c /path/to/kong/conf] +``` + +## Enable LDAP Authentication and enforce RBAC + +To enable LDAP Authentication and enforce RBAC for Kong Manager, configure Kong with the following properties: + +``` +admin_gui_auth = ldap-auth-advanced +enforce_rbac = on +``` + +**Note**: When enabling LDAP Authentication in this step, you are enabling and configuring the LDAP Authentication Advanced Plugin for Kong Manager. No other configuration for the plugin is needed. + +## Configure the Sessions plugin + +Configure the Sessions Plugin for Kong Manager: + +``` +admin_gui_session_conf = { "secret":"set-your-string-here" } +``` + +>Note: The **Sessions Plugin** requires a **secret** and is configured securely by default: + +* Under all circumstances, the secret must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to false. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. Learn more about these properties in [_Session Security in Kong Manager_](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/), and see [_example configurations_](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +## Configure LDAP Authentication for Kong Manager + +Configure LDAP Authentication for Kong Manager with the following properties. Note the attribute variables are defined below: + +``` +admin_gui_auth_conf = { + "anonymous":"", \ + "attribute":"", \ + "bind_dn":"", \ + "base_dn":"", \ + "cache_ttl": 2, \ + "header_type":"Basic", \ + "keepalive":60000, \ + "ldap_host":"", \ + "ldap_password":"", \ + "ldap_port":389, \ + "start_tls":false, \ + "timeout":10000, \ + "verify_ldap_host":true, \ + "consumer_by":["username", "custom_id"], \ + "group_base_dn":"", + "group_name_attribute":"", + "group_member_attribute":"", +} +``` + +* `attribute`:``: The attribute used to identify LDAP users + * For example, to map LDAP users to admins by their username, `attribute":"uid` +* `bind_dn`:``: LDAP Bind DN (Distinguished Name) + * Used to perform LDAP search of user. This `bind_dn` should have permissions to search for the user being authenticated. + * For example, `uid=einstein,ou=scientists,dc=ldap,dc=com` +* `base_dn`:``: LDAP Base DN (Distinguished Name) + * For example, `ou=scientists,dc=ldap,dc=com` +* `ldap_host`:``: LDAP host domain. + * For example, `ec2-XX-XXX-XX-XXX.compute-1.amazonaws.com` +* `ldap_port`: The default LDAP port is 389. 636 is the port required for SSL LDAP and AD. + If `ldaps` is configured, you must use port 636. For more complex Active Directory (AD) environments, + instead of Domain Controller and port 389, consider using a Global Catalog host and port, which is port 3268 by default. +* `ldap_password`:``: LDAP password + * *Important*: As with any configuration property, sensitive information may be set as an environment variable instead of being written directly in the configuration file. +* `group_base_dn`:``: Sets a distinguished name for the entry where LDAP searches for groups begin. The default is the value from `conf.base_dn`. +* `group_name_attribute`: ``: Sets the attribute holding the name of a group, typically called `name` (in Active Directory) or `cn` (in OpenLDAP). The default is the value from `conf.attribute`. +* `group_member_attribute`:``: Sets the attribute holding the members of the LDAP group. The default is `memberOf`. + +## Define Roles with Permissions + +Define Roles with Permissions in {{site.base_gateway}}, using the Admin API's [_RBAC endpoints_](/gateway/{{page.release}}/admin-api/rbac/reference/#update-or-create-a-role) or using Kong Manager's Teams > [Admins tab](/gateway/{{page.release}}/configure/auth/rbac/add-user/). You must manually define which Kong Roles correspond to each of the Service Directory's Groups using either of the following: + +In Kong Manager's Directory Mapping section. Go to Teams > Groups tab. +With the Admin API's Directory Mapping endpoints. + +{{site.base_gateway}} will not write to the Service Directory, for example, a {{site.base_gateway}} Admin cannot create Users or Groups in the directory. You must create Users and Groups independently before mapping them to {{site.base_gateway}}. + +## User-Admin Mapping + +To map a Service Directory User to a Kong Admin, you must configure the Admin's username as the value of the User's name from their LDAP Distinguished Name (DN) corresponding the attribute configured in `admin_gui_auth_conf`. Creating an Admin account in [_Kong Manager_](/gateway/{{page.release}}/configure/auth/rbac/add-admin/) or using the [_Admin API_](/gateway/{{page.release}}/admin-api/admins/reference/#invite-an-admin). + +For instructions on how to pair the bootstrapped Super Admin with a Directory User, see [_How to Set Up a Service Directory User as the First Super Admin_](/gateway/{{page.release}}/configure/auth/service-directory-mapping/#set-up-a-directory-user-as-the-first-super-admin). + +If you already have Admins with assigned Roles and want to use Group mapping instead, it is necessary to first remove all of their Roles. The Service Directory will serve as the system of record for User privileges. Assigned Roles will affect a user's privileges in addition to any roles mapped from Groups. + +## Group-Role Assignment + +Using Service Directory Mapping, Groups to Roles are mapped. When a user logs in, they are identified with their Admin username and then authenticated with the matching User credentials in the Service Directory. The Groups in the Service Directory are then automatically matched to the associated Roles that the organization has defined. + +### Example + +1. Wayne Enterprises maps the Service Directory Group, T1-Mgmt, to the Kong Role super-admin. +2. Wayne Enterprises maps a Service Directory User, named bruce-wayne, to a Kong Admin account with the same name, bruce-wayne. +3. The User, bruce-wayne, is assigned to the Group T1-Mgmt in the LDAP Directory. + + +When bruce-wayne logs in as an Admin to Kong Manager, they will automatically have the Role of super-admin as a result of the mapping. + +If Wayne Enterprises decides to revoke bruce-wayne's privileges by removing their assignment to T1-Mgmt, they will no longer have the super-admin Role when they attempt to log in. + +## Set Up a Directory User as the First Super Admin + +**Important**: Setting up a Directory User as the first Super Admin is recommended by Kong. + + +The following is an example of setting up a Directory User as the first Super Admin. +The example shows an attribute is configured with a unique identifier (UID), and the Directory User you want to make the Super Admin has a distinguished name (DN) entry of `UID=bruce-wayne`: + +``` +HTTPie +$ http PATCH :8001/admins/kong_admin username="bruce-wayne" +Kong-Admin-Token: +cURL +$ curl --request 'PATCH' --header 'Kong-Admin-Token: ' --header +'Content-Type: application/json' --data '{"username":"bruce-wayne"}' +'localhost:8001/admins/kong_admin' +``` + +This User will be able to log in, but until you map a Group belonging to bruce-wayne to a Role, the User will only use the Directory for authentication. Once you map the super-admin Role to a Group that bruce-wayne is in, then you can delete the super-admin Role from the bruce-wayne Admin. Note the group you pick needs to be “super” in your directory, otherwise as other admins log in with a generic group, for example the “employee” group, they will also become super-admins. + +**Important**: If you delete the super-admin Role from your only Admin, and have not yet mapped the super-admin Role to a Group that Admin belongs to, then you will not be able to log in to Kong Manager. + +Alternatives: + +* Start Kong with RBAC turned off, map a Group to the super-admin Role, and then create an Admin to correspond to a User belonging to that Group. Doing so ensures that the Super Admin's privileges are entirely tied to the Directory Group, whereas bootstrapping a Super Admin only uses the Directory for authentication. + +Create all Admin accounts for matching Directory Users and ensure that their existing Groups map to appropriate Roles before enforcing RBAC. diff --git a/app/gateway/2.7.x/configure/graphql-quickstart.md b/app/gateway/2.7.x/configure/graphql-quickstart.md new file mode 100644 index 000000000000..4c79694b6d5a --- /dev/null +++ b/app/gateway/2.7.x/configure/graphql-quickstart.md @@ -0,0 +1,62 @@ +--- +title: Getting Started with GraphQL and Kong Gateway +badge: enterprise +--- + +GraphQL decouples apps from services by introducing a flexible query language. Instead of a custom API for each screen, app developers describe the data they need, service developers describe what they can supply, and GraphQL automatically matches the two together. Teams ship faster across more platforms, with new levels of visibility and control over the use of their data. To learn more about how teams benefit, read why [GraphQL is important](https://www.apollographql.com/why-graphql/). + +{{site.base_gateway}} is an API gateway and platform. That means it is a form of middleware between computing clients and your API-based applications. {{site.base_gateway}} quickly and consistently extends the features of your APIs. Some of the popular features deployed through {{site.base_gateway}} include authentication, security, traffic control, serverless, analytics & monitoring, request/response transformations, and logging. To learn more about these features, see the [Hub page](/hub/) for plugins. For more about the benefits of Kong in general, please see the [FAQ](https://konghq.com/faqs). + +The GraphQL paradigm differs from traditional API-based systems. Depending on the resolver implementation details, one query can potentially generate an arbitrary number of requests. Proxy caching and rate limiting on top of GraphQL is key but usually overlooked as a hard problem to solve, since traditional proxy-caching and rate-limiting is not a good fit for GraphQL. + +Kong easily integrates with existing GraphQL infrastructure out of the box. By introspecting the GraphQL schema and queries, Kong provides enterprise-grade proxy-caching and rate-limiting specifically tailored for GraphQL. + +## Existing GraphQL infrastructure + +Use {{site.base_gateway}} to protect and manage an existing GraphQL endpoint. The following will set up a {{site.base_gateway}} instance on top of a GraphQL upstream and set up key-auth, proxy-caching and rate-limiting. + +### Add your Service and Route on Kong + +After installing and starting {{site.base_gateway}}, use the Admin API on port 8001 to add a new Service and Route. In this example, {{site.base_gateway}} will reverse proxy every incoming request with the specified incoming host to the associated upstream URL. You can implement very complex routing mechanisms beyond simple host matching. + + +``` +$ curl -i -X POST \ + --url http://localhost:8001/services/ \ + --data 'name=graphql-service' \ + --data 'url=http://example.com' +$ curl -i -X POST \ + --url http://localhost:8001/services/graphql-service/routes \ + --data 'hosts[]=example.com' \ +``` + +### Add GraphQL Plugins on the Service + +Proxy caching for GraphQL provides advanced caching over queries. + +``` +$ curl -i -X POST \ + --url http://localhost:8001/services/graphql-service/plugins/ \ + --data 'name=graphql-proxy-cache-advanced' \ + --data 'config.strategy=memory' +``` + +Protect your upstream GraphQL service with rate limiting. By introspecting your schema, it will analyze query costs and provide an enterprise-grade rate-limiting strategy. + +``` +$ curl -i -X POST http://localhost:8001/services/graphql-service/plugins \ + --data name=graphql-rate-limiting-advanced \ + --data config.limit=100,10000 \ + --data config.window_size=60,3600 \ + --data config.sync_rate=10 +``` + +The GraphQL Rate Limiting Advanced plugin supports two rate-limiting strategies. The default strategy will try to estimate cost on queries by counting the nesting of nodes. The default strategy is meant as a good middle ground for general GraphQL queries, where it's difficult to assert a clear cost strategy, so every operation has a cost of 1. + +A more advanced strategy is available for GraphQL schemas that enforce quantifier arguments on any connection, providing a good approximation on the number of nodes visited for satisfying a query. Any query without decorated quantifiers has a cost of 1. It is roughly based on [GitHub's GraphQL resource limits](https://developer.github.com/v4/guides/resource-limitations/). + +Read more about rate-limiting here: [GraphQL Rate Limiting Advanced Plugin](/hub/kong-inc/graphql-rate-limiting-advanced/) + +### New upstream + +We have prepared a [quickstart guide](https://github.com/Kong/kong-apollo-quickstart) that will help you build your new GraphQL service on top of Kong and Apollo. diff --git a/app/gateway/2.7.x/configure/grpc.md b/app/gateway/2.7.x/configure/grpc.md new file mode 100644 index 000000000000..56cbe14e3edc --- /dev/null +++ b/app/gateway/2.7.x/configure/grpc.md @@ -0,0 +1,170 @@ +--- +title: Introduction to Kong gRPC Plugins +--- + +Before going into the specifics of configuring Kong's gRPC plugins, let's +discuss the advantages of the gRPC protocol. Unlike JSON, +[gRPC](https://en.wikipedia.org/wiki/GRPC) +is a binary protocol, using [protobuf](https://en.wikipedia.org/wiki/Protocol_Buffers) +definitions to instruct how the data is marshalled and unmarshalled. Because +binary data is used instead of text, it's a more efficient way to transmit data +over a network. However, this also makes gRPC harder to work with, because inspecting +what went wrong is more challenging. Additionally, few clients natively handle gRPC. + +To help alleviate the challenges of working with gRPC, Kong has two plugins: +- [gRPC-Gateway](/hub/kong-inc/grpc-gateway/) +- [gRPC-Web](/hub/kong-inc/grpc-web/) + +The gRPC-Gateway plugin allows you to send JSON requests to a gRPC service. A +specially configured `.proto` file handles the conversion of the JSON request +into one that the gRPC service can handle. This allows you to expose RESTful-style +interfaces that talk to a gRPC service. + +The gRPC-Web plugin allows you to interact with a gRPC service from a browser. +Instead of presenting a RESTful-type call, you POST data to the same +gRPC service endpoint that the protobuf defines. + +For flexibility and compatibility with RESTful expectations, the gRPC-Gateway +plugin offers more configurability, whereas the gRPC-Web plugin adheres more +directly to the protobuf specification. + +Let's walk through setting up each plugin so you can see how they work. + +## gRPC-Gateway plugin configuration + +Set up a Service: + +``` +curl -X POST kong-cp-host:8001/services \ +--data 'name=grpcbin-service' \ +--data 'url=grpc://grpcb.in:9000' +``` + +Set up the Route to the Service: + +``` +curl -X POST kong-cp-host:8001/services/grpcbin-service/routes \ +--data 'name=grpcbin-get-route' \ +--data 'paths=/' \ +--data 'methods=GET' \ +--data 'headers.x-grpc=true' +``` + +Set up the gRPC-Web plugin: + +``` +curl -X POST kong-cp-host:8001/routes/grpcbin-get-route/plugins \ +--data 'name=grpc-gateway' \ +--data 'config.proto=/usr/local/kong/hello-gateway.proto' +``` + +Protobuf definition (`hello-gateway.proto`): + +``` +syntax = "proto3"; + +package hello; + +service HelloService { + rpc SayHello(HelloRequest) returns (HelloResponse) { + option (google.api.http) = { + get: "/v1/messages/{name}" + additional_bindings { + get: "/v1/messages/legacy/{name=**}" + } + post: "/v1/messages/" + body: "*" + } + } +} + + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloResponse { + string message = 1; +} +``` + +Upload the protobuf definition to your Kong Node: + +``` +docker cp hello-gateway.proto kong-dp-host:/usr/local/kong/ +``` + +Test your setup: + +``` +curl -X GET kong-dp-host:8000/v1/messages/kong2.1 \ +--header 'x-grpc: true' +``` + +## gRPC-Web plugin configuration + +Set up a Service: + +``` +curl -X POST kong-cp-host:8001/services \ +--data 'name=grpcbin-service' \ +--data 'url=grpc://grpcb.in:9000' +``` + +Set up the Route to the Service: + +``` +curl -X POST kong-cp-host:8001/services/grpcbin-service/routes \ +--data 'name=grpcbin-post-route' \ +--data 'paths=/' \ +--data 'methods=POST' \ +--data 'headers.x-grpc=true' +``` + +Set up the gRPC-Web plugin: + +``` +curl -X POST kong-cp-host:8001/routes/grpcbin-post-route/plugins \ +--data 'name=grpc-web' \ +--data 'config.proto=/usr/local/kong/hello.proto' +``` + +Protobuf definition (`hello.proto`): + +``` +syntax = "proto2"; + +package hello; + +service HelloService { + rpc SayHello(HelloRequest) returns (HelloResponse); + rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse); + rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse); + rpc BidiHello(stream HelloRequest) returns (stream HelloResponse); +} + +message HelloRequest { + optional string greeting = 1; +} + +message HelloResponse { + required string reply = 1; +} +``` + +Upload the protobuf definition to your Kong Node: + +``` +docker cp hello.proto kong-dp-host:/usr/local/kong/ +``` + +Test your setup: + +``` +curl -X POST kong-dp-host:8000/hello.HelloService/SayHello \ +--header 'x-grpc: true' \ +--header 'Content-Type: application/json' \ +--data '{"greeting":"kong2.1"}' +``` diff --git a/app/gateway/2.7.x/configure/logging.md b/app/gateway/2.7.x/configure/logging.md new file mode 100644 index 000000000000..fb656b2e23cd --- /dev/null +++ b/app/gateway/2.7.x/configure/logging.md @@ -0,0 +1,144 @@ +--- +title: Logging Reference +--- + +## Log Levels + +Log levels are set in [Kong's configuration](/gateway/{{page.release}}/reference/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. + +`notice` is the default and recommended log level. 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 in the [Configuration Property reference](/gateway/{{page.release}}/reference/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 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';`. 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 `proxy_access_log` by either editing `etc/kong/kong.conf` or 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/gateway/2.7.x/configure/network.md b/app/gateway/2.7.x/configure/network.md new file mode 100644 index 000000000000..7490bbbcb503 --- /dev/null +++ b/app/gateway/2.7.x/configure/network.md @@ -0,0 +1,71 @@ +--- +title: Network and Firewall +--- + +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]. + +{% include_cached /md/admin-listen.md release=page.release desc='short' %} + +* `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]: /gateway/{{page.release}}/reference/configuration/#proxy_listen +[stream_listen]: /gateway/{{page.release}}/reference/configuration/#stream_listen +[admin_listen]: /gateway/{{page.release}}/reference/configuration/#admin_listen +[secure_admin_api]: /gateway/{{page.release}}/admin-api/secure-admin-api diff --git a/app/gateway/2.7.x/developer-portal/administration/application-registration/3rd-party-oauth.md b/app/gateway/2.7.x/developer-portal/administration/application-registration/3rd-party-oauth.md new file mode 100644 index 000000000000..459510b78ea6 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/administration/application-registration/3rd-party-oauth.md @@ -0,0 +1,151 @@ +--- +title: Third-party OAuth2 Support for Application Registration +badge: enterprise +--- + +Third-party OAuth2 support allows developers to centralize application +credentials management with the [supported Identity Provider](#idps) of their +choice. To use the external IdP feature, set the `portal_app_auth` +configuration option to `external-oauth2` in the +`kong.conf.default` configuration file. For more information, see setting the +[Authorization Provider Strategy](/gateway/{{page.release}}/developer-portal/administration/application-registration/auth-provider-strategy). + +The Kong [OIDC](/hub/kong-inc/openid-connect/) and +[Portal Application Registration](/hub/kong-inc/application-registration/) +plugins are used in conjunction with each other on a Service: + +* The OIDC plugin handles all aspects of the OAuth2 handshake, including +looking up the Consumer via +[custom claim](/gateway/{{page.release}}/developer-portal/administration/application-registration/okta-config#auth-server-cclaim) +(the `custom_id` matches the identity provider `client_id` claim). + +* The Application Registration plugin is responsible for checking the mapped +Consumer and ensuring the Consumer has the correct ACL (Access Control List) +permissions to access the Route. + +## Supported identity providers {#idps} + +The Kong OIDC plugin supports many identity providers out of the box. The +following providers have been tested for the current version of the Kong +Portal Application Registration plugin used in tandem with the Kong OIDC plugin: + +* [Okta](https://developer.okta.com/). See the + [Okta setup example](/gateway/{{page.release}}/developer-portal/administration/application-registration/okta-config/). +* [Azure](https://azure.microsoft.com/). See the + [Azure setup example](/gateway/{{page.release}}/developer-portal/administration/application-registration/azure-oidc-config/). +* [Ping Identity](https://www.pingidentity.com/). + +### Resources + +How you authenticate with a Service depends on its underlying OAuth2 +implementation. For more information, reference the documentation below for +your implemented identity provider and OAuth flow. + +- Okta + - [Authorization Code Flow](https://developer.okta.com/docs/guides/implement-auth-code/overview/) + - [Authorization Code Flow (PKCE)](https://developer.okta.com/docs/guides/implement-auth-code-pkce/overview/) + - [Client Credentials Flow](https://developer.okta.com/docs/guides/implement-client-creds/overview/) + - [Implicit Grant Flow](https://developer.okta.com/docs/guides/implement-implicit/overview/) + +- Azure + - [Authorization Code Flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow) + - [Client Credentials Flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow) + - [Implicit Grant Flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-implicit-grant-flow) + +- Ping Identity + - [Oauth2 Developers Guide](https://www.pingidentity.com/developer/en/resources/oauth-2-0-developers-guide.html) + +## Supported OAuth flows + +* Client Credentials ([RFC 6742 Section 4.4](https://tools.ietf.org/html/rfc6749#section-4.4)) +* Authorization Code ([RFC 6742 Section 4.1](https://tools.ietf.org/html/rfc6749#section-4.1)) +* Implicit Grant ([RFC 6742 Section 4.2](https://tools.ietf.org/html/rfc6749#section-4.2)) +* Password Grant ([RFC 6742 Section 4.3](https://tools.ietf.org/html/rfc6749#section-4.3)) + +Password Grant and [Implicit Grant flows](https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead) are available but not recommended +because they are less secure than the Authorization Code and Client Credentials +flows. + +### Client Credentials Flow {#cc-flow} + +The OIDC plugin makes authenticating using Client Credentials very +straightforward. This flow should be used for server-side and secure +machine-to-machine communication. The Client Credentials flow requires the +authorizing party to store and send the application's `client_secret`. + +In this flow, a developer makes a request against the Service with the OIDC and Application +Registration plugins applied. This request should contain the `client_id` and +`client_secret` as a Basic Auth authentication header: + +`Authorization: Basic client_id:client_secret` + +The `client_id:client_secret` should be base64-encoded. + +The following sequence diagram illustrates the Client Credentials flow through +the OIDC and Application Registration plugins. Click on the image to expand its + view. + +![Client Credentials Flow](/assets/images/products/gateway/dev-portal/dp-appreg-3rdparty-ccflow.png) + +| Step | Explanation | +|:------|:---------------------------------------------------------------------| +| a | Developer sends the Okta application's `client_id` and `client_secret` to the Route. The OIDC plugin proxies this request to the Okta auth server's endpoint.| +| b | Okta reads the `client_id` and `client_secret` and generates an access token. The auth server is configured to insert a custom claim `application_id`, which is a key/value pair with the Okta application's `client_id`. | +| c | Okta returns the access token to Kong. | +| d | The OIDC plugin reads the resulting access token and associates the request with the application via the `application_id` custom claim. | +| e | If the resolved application has permission to consume the Service via its Portal Application Registration plugin, Kong forwards the request to the Upstream. | + +### Authorization Code Flow {#ac-flow} + +Due to limitations of the OIDC plugin, a single plugin instance cannot handle +dynamic `client_id's` provisioned from multiple sources (applications). +To circumvent this issue, the IdP Issuer URL is exposed to developers on the +Dev Portal application show page when +[`show_issuer`](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration#app-reg-params) is enabled in the +Application Registration plugin. Developers can hit the Issuer URL directly to +provision an access token. After getting the access token, requests can be made +against the proxy. + +1. Set up the application to secure an access token against the IdP directly. +For more information about implementing the Authorization Code flow with Okta, +refer to the +[Okta developer guide](https://developer.okta.com/docs/guides/implement-auth-code/overview/). + +2. After the initial access token handshake has been completed, make subsequent +requests to the Kong service using that access token as a +[bearer token](https://tools.ietf.org/html/rfc6750#section-2.1). After +the first successful request, the OIDC plugin will establish a session with the +client so that the access token does not need to be continually passed with +every request. + +The following sequence diagram illustrates the Authorization Code flow through +the OIDC and Application Registration plugins. Click on the image to expand its + view. + +![Authorization Code Flow](/assets/images/products/gateway/dev-portal/dp-appreg-3rdparty-authcodeflow.png) + +| Step | Explanation | +|:------|:--------------------------------------------------------------------| +| a | A developer copies the target Service's `issuer_id`, which can be exposed in the Dev Portal application view Service Details page. Developers can configure their application to make a request to this endpoint to authenticate the user and retrieve an access token. | +| b | Okta redirects the user to a login page. | +| c | The user inputs their Single Sign-On (SSO) information. | +| d | The user submits the SSO form that contains their Okta username and password. | +| e | Upon a successful login, the application is given an access token to make against calls for all subsequent requests. | +| f | The user makes a request to the protected Service and Route.| +| g | The OIDC plugin takes the access token and runs introspection, consulting the Okta authorization server if necessary. After the access token has been verified, the plugin matches the custom claim to find the associated application Consumer via its `custom_id`. | +| h | The request is passed to the Application Registration plugin, which checks to make sure the Consumer has the appropriate ACL (Access Control List) permissions. | +| i | The request is proxied to the Upstream. | + +### Implicit Grant Flow + +The Implicit Grant flow is not recommended if the Authorization Code flow is +possible. + +1. Set up the application to secure an access token against the IdP directly. +For more information about implementing the Implicit Grant flow with Okta, refer to +the [Okta developer guide](https://developer.okta.com/docs/guides/implement-implicit/use-flow/). + +2. After the access token handshake has been completed, make subsequent requests +to the Kong service using that access token as a bearer token. After the first +successful request, the OIDC plugin will establish a session with the client so +that the access token does not need to be passed continuously. diff --git a/app/gateway/2.7.x/developer-portal/administration/application-registration/auth-provider-strategy.md b/app/gateway/2.7.x/developer-portal/administration/application-registration/auth-provider-strategy.md new file mode 100644 index 000000000000..238665831431 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/administration/application-registration/auth-provider-strategy.md @@ -0,0 +1,74 @@ +--- +title: Authorization Provider Strategy for Application Registration +badge: enterprise +--- + +You can use {{site.base_gateway}} or an external system of record with the +Application Registration plugin. + +The `portal_app_auth` configuration option must be set in `kong.conf` to enable +the Dev Portal Application Registration plugin with your chosen +authorization strategy: + +* `kong-oauth2`: Default. {{site.base_gateway}} is the system of record. The Application + Registration plugin is used in conjunction with the [OAuth2](/hub/kong-inc/oauth2/) or + [Key Authentication](/hub/kong-inc/key-auth/) plugin. + + {:.note} + > **Note**: The OAuth2 plugin can only be used with + traditional deployments. Because the OAuth2 plugin requires a database + for every gateway instance, it can't be used with hybrid mode or DB-less + deployments. + +* `external-oauth2`: An external IdP is the system of record. The + Portal Application Registration plugin is used in conjunction with the + [OpenID Connect (OIDC)](/hub/kong-inc/openid-connect/) plugin. + The `external-oauth2` option can be used with any deployment type. + + The third-party authorization strategy (`external-oauth2`) applies to all + applications across all Workspaces (Dev Portals) in a {{site.base_gateway}} cluster. + +## Using the {{site.base_gateway}} auth strategy + +If you're using the default `kong-oauth2` authorization strategy with {{site.base_gateway}} as the system of record, set up app registration using the following steps: + +1. Enable the [Application Registration plugin](/gateway/{{page.release}}/kong-enterprise/dev-portal/applications/enable-application-registration/) on a service. + +2. Configure either the [OAuth2](/hub/kong-inc/oauth2/) plugin or the [Key Auth](/hub/kong-inc/key-auth/) plugin on the same service as the Application Registration plugin. + + The OAuth2 plugin can't be used in hybrid mode. + +## Setting external portal authentication {#set-external-oauth2} + +If you are using an external IdP (`external-oauth2`), follow these steps. + +1. Review and choose one of the +[recommended workflows](/gateway/{{page.release}}/kong-enterprise/dev-portal/authentication/3rd-party-oauth#supported-oauth-flows). + +1. Open `kong.conf.default` and set the `portal_app_auth` option to your chosen + strategy. The example configuration below switches from the default + (`kong-oauth2`) to an external IdP (`external-oauth2`). + + ``` + portal_app_auth = external-oauth2 + # Dev Portal application registration + # auth provider and strategy. Must be set to configure + # authentication in conjunction with the application_registration plugin. + # Currently accepts kong-oauth2 or external-oauth2. + ``` + +1. Restart your {{site.base_gateway}} instance. + + ``` + kong reload + ``` + +1. Enable the [Application Registration plugin](/gateway/{{page.release}}/kong-enterprise/dev-portal/applications/enable-application-registration/) on a service. + +1. Configure the [OIDC plugin](/hub/kong-inc/openid-connect/) on the same service as the + Application Registration plugin. + +1. Configure the identity provider for your application, configure your +application in {{site.base_gateway}}, and associate them with each other. See the +[Okta](/gateway/{{page.release}}/kong-enterprise/dev-portal/authentication/okta-config/) +or the [Azure](/gateway/{{page.release}}/kong-enterprise/dev-portal/authentication/azure-oidc-config/) setup examples. diff --git a/app/gateway/2.7.x/developer-portal/administration/application-registration/azure-oidc-config.md b/app/gateway/2.7.x/developer-portal/administration/application-registration/azure-oidc-config.md new file mode 100644 index 000000000000..12fd9b4ac346 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/administration/application-registration/azure-oidc-config.md @@ -0,0 +1,265 @@ +--- +title: Set Up External Portal Application Authentication with Azure AD and OIDC +badge: enterprise +--- + +These instructions help you set up Azure AD as your third-party identity provider +for use with the Kong OIDC and Portal Application Registration plugins. + +## Prerequisites + +- The `portal_app_auth` configuration option is configured for your OAuth provider + and strategy (`kong-oauth2` or `external-oauth2`). See + [Configure the Authorization Provider Strategy](/gateway/{{page.release}}/developer-portal/administration/application-registration/auth-provider-strategy/) for the Portal Application Registration plugin. + +## Create an Application in Azure + +1. Within Azure, go to the **App registrations** service and register a new application. + +2. In **Certificates & secrets**, create a Client secret and save it in a + secure location. You can only view the secret once. + +3. Under **Manifest**, update `accessTokenAcceptedVersion=2` (default is null). + The JSON for your application should look similar to this example: + +## Create a Service in Kong + +{% navtabs %} +{% navtab Using cURL %} + +```bash +curl -i -X PUT http://localhost:8001/services/httpbin-service-azure \ + --data 'url=https://httpbin.konghq.com/anything' +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +http PUT :8001/services/httpbin-service-azure \ + url=https://httpbin.konghq.com/anything +``` +{% endnavtab %} +{% endnavtabs %} + +## Create a Route in Kong + +{% navtabs %} +{% navtab Using cURL %} + +```bash +curl -i -X PUT http://localhost:8001/services/httpbin-service-azure/routes/httpbin-route-azure \ + --data 'paths=/httpbin-azure' +``` +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +http -f PUT :8001/services/httpbin-service-azure/routes/httpbin-route-azure \ + paths=/httpbin-azure +``` + +{% endnavtab %} +{% endnavtabs %} + +## Map the OIDC and Application Registration Plugins to the Service + +Map the OpenID Connect and Application Registration plugins to the **Service**. +The plugins must be applied to a Service to work properly. + +### Step 1: Configure the OIDC plugin for the Service + + +{% navtabs %} +{% navtab Using cURL %} + + ```bash +curl -X POST http://localhost:8001/services/httpbin-service-azure/plugins \ + --data name=openid-connect \ + --data config.issuer="https://login.microsoftonline.com//v2.0" \ + --data config.display_errors="true" \ + --data config.client_id="" \ + --data config.client_secret="" \ + --data config.redirect_uri="https://example.com/api" \ + --data config.consumer_claim=aud \ + --data config.scopes="openid" \ + --data config.scopes="YOUR_CLIENT_ID/.default" \ + --data config.verify_parameters="false" +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +http -f :8001/services/httpbin-service-azure/plugins \ + name=openid-connect \ + config.issuer=https://login.microsoftonline.com//v2.0 \ + config.display_errors=true \ + config.client_id= \ + config.client_secret="" \ + config.redirect_uri="https://example.com/api" \ + config.consumer_claim=aud \ + config.scopes=openid \ + config.scopes=/.default \ + config.verify_parameters=false +``` +{% endnavtab %} +{% endnavtabs %} + +For more information, see [OIDC plugin](/hub/kong-inc/openid-connect/). + + +### Step 2: Configure the Application Registration plugin for the Service + +{% navtabs %} +{% navtab Using cURL %} + +```bash +curl -X POST http://localhost:8001/services/httpbin-service-azure/plugins \ + --data "name=application-registration" \ + --data "config.auto_approve=true" \ + --data "config.description=Uses consumer claim with various values (sub, aud, etc.) as registration id to support different flows and use cases." \ + --data "config.display_name=For Azure" \ + --data "config.show_issuer=true" +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +http -f :8001/services/httpbin-service-azure/plugins \ + name=application-registration \ + config.auto_approve=true \ + config.display_name="For Azure" \ + config.description="Uses consumer claim with various values (sub, aud, etc.) as registration id to support different flows and use cases." \ + config.show_issuer=true +``` +{% endnavtab %} +{% endnavtabs %} + +### Step 3: Get an access token from Azure + +Get an access token using the Client Credential workflow and convert the token +into a JSON Web Token (JWT). Replace the placeholder values with your values for +``, ``,``, and +``. + +Get an access token from Azure: + +{% navtabs %} +{% navtab Using cURL %} + +```bash +curl -X POST https://login.microsoftonline.com//oauth2/v2.0/token \ + --data scope="/.default" \ + --data grant_type="client_credentials" \ + --data client_id="" \ + --data client_secret="" \ +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +https -f POST "https://login.microsoftonline.com//oauth2/v2.0/token" \ + scope=/.default \ + grant_type=client_credentials \ + -a : +``` +{% endnavtab %} +{% endnavtabs %} + +### Step 4: Convert an access token into a JWT token + +1. Paste the access token obtained from the previous step into +[JWT](https://jwt.io). + +1. Click **Share JWT** to copy the value for the +[aud (audience)](https://tools.ietf.org/html/rfc7519#section-4.1.3) claim to +your clipboard. You will use the `aud` value as your **Reference ID** in the +next procedure. + +## Create an Application in Kong + +1. Log in to your Dev Portal and create a new application: + 1. Select the **My Apps** menu -> **New Application**. + 2. Enter the **Name** of your Azure application. + 3. Paste the `aud` value generated in JWT in the **Reference ID** field. + 4. (Optional) Enter a **Description**. + +2. Click **Create**. + +3. After you create your application, make sure you activate the Service. In the + Services section of the Application Dashboard, click **Activate** on the Service + you want to use. + + Because you enabled + [Auto-approve](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration##aa) + on the associated Application Registration Plugin, an admin won't need to + approve the request. + +## Test your Authentication Flows with your Azure Application + +Follow these instructions to test your client credentials or authorization code +flows with your Azure AD implementation. + +### Test Client Credentials Flow + +#### Step 1: Get a token + +{% navtabs %} +{% navtab Using cURL %} + +```bash +$ curl -X POST "https://login.microsoftonline.com//oauth2/v2.0/token" \ +--data scope="/.default" \ +--data grant_type="client_credentials" \ +--data client_id="" \ +--data client_secret="" +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +$ https -f POST "https://login.microsoftonline.com//oauth2/v2.0/token" \ + scope=/.default \ + grant_type=client_credentials \ + -a : \ + --verify NO +``` +{% endnavtab %} +{% endnavtabs %} + +#### Step 2: Use the token in an authorization header to retrieve the data + +{% navtabs %} +{% navtab Using cURL %} + +```bash +curl --header 'Authorization: bearer ' ':8000/httpbin-azure' +``` + +{% endnavtab %} +{% navtab Using HTTPie %} + +```bash +http :8000/httpbin-azure Authorization:'bearer ' +``` +{% endnavtab %} +{% endnavtabs %} + + Replace `` with the bearer token you generated in the previous step. + +### Test Authorization Code Flow + +In your browser, go to `http://localhost:8000/httpbin-azure`. + +You should be guided through a log in process within Azure and then the results +delivered in your browser. + +## Troubleshoot + +If you encounter any issues, review your data plane logs. Because you +enabled `display_errors=true` on the OpenID Connect Plugin, you will receive +more verbose error messages that can help pinpoint any issues. diff --git a/app/gateway/2.7.x/developer-portal/administration/application-registration/enable-application-registration.md b/app/gateway/2.7.x/developer-portal/administration/application-registration/enable-application-registration.md new file mode 100644 index 000000000000..ed3ec5dcf9ca --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/administration/application-registration/enable-application-registration.md @@ -0,0 +1,66 @@ +--- +title: Enable Application Registration +badge: enterprise +--- + +Application registration allows registered developers on the Kong Dev Portal to +authenticate with supported authentication plugins against a service on Kong. +Either {{site.base_gateway}} or external identity provider admins can selectively +admit access to services using Kong Manager. + +## Prerequisites + +* Dev Portal is enabled on the same workspace as the service. +* The service is created and enabled with HTTPS. +* Authentication is enabled on the Dev Portal. +* Logged in as an admin with read and write roles on applications, services, and + developers. +* The `portal_app_auth` configuration option is configured for your OAuth provider + and strategy (`kong-oauth2` default or `external-oauth2`). See +[Configure the Authorization Provider Strategy](/gateway/{{page.release}}/developer-portal/administration/application-registration/auth-provider-strategy/) for the Portal Application Registration plugin. +* Authorization provider configured if using a supported third-party + identity provider with the OIDC plugin: + * For example instructions using Okta as an identity provider, refer to the + [Okta example](/gateway/{{page.release}}/developer-portal/administration/application-registration/okta-config/). + * For example instructions using Azure AD as an identity provider, refer to the + [Azure example](/gateway/{{page.release}}/developer-portal/administration/application-registration/azure-oidc-config/). + +## Enable application registration on a service using Kong Manager {#enable-app-reg-plugin} + +To use application registration on a service, enable the Portal Application Registration +plugin. + +In Kong Manager, access the service for which you want to enable application registration: + +1. From your workspace, in the left navigation pane, go to **API Gateway > Services**. +2. On the Services page, select the service and click **View**. +3. In the Plugins pane in the Services page, click **Add a Plugin**. +4. On the Add New Plugin page in the Authentication section, find the + **Portal Application Registration** plugin and click **Enable**. + +5. Enter the configuration settings. Use the parameters in the next section, + [Application Registration Configuration Parameters](#application-registration-configuration-parameters), + to complete the fields. + + {:.important} + > **Important:** Exposing the Issuer URL is essential for the + [Authorization Code Flow](/gateway/{{page.release}}/developer-portal/administration/application-registration/3rd-party-oauth/#ac-flow) + workflow configured for third-party identity providers. + +6. Click **Create**. + +### Application registration configuration parameters {#app-reg-params} + +| Form Parameter | Description | +|:---------------|:----------------------------------------------------------------------------------| +| `Service` | The service that this plugin configuration will target. Required. | +| `Tags` | A set of strings for grouping and filtering, separated by commas. Optional. | +| `Auto Approve` | If enabled, all new service contract requests are automatically approved. Otherwise, Dev Portal admins must manually approve requests. Default: `false`. | +| `Description` | Description displayed in the information about a service in the Dev Portal. Optional. | +| `Display Name` | Unique name displayed in the information about a service in the Dev Portal. Required. | +| `Show Issuer` | Displays the Issuer URL in the Service Details page. Default: `false`. **Important:** Exposing the **Issuer URL** is essential for the [Authorization Code Flow](/gateway/{{page.release}}/developer-portal/administration/application-registration/3rd-party-oauth/#ac-flow) workflow configured for third-party identity providers. | + +## Next steps + +Choose an [authorization strategy](/gateway/{{page.release}}/developer-portal/administration/application-registration/auth-provider-strategy/) +and configure the appropriate plugin: OAuth2, Key Authentication, or OpenID Connect. diff --git a/app/gateway/2.7.x/developer-portal/administration/application-registration/enable-key-auth-plugin.md b/app/gateway/2.7.x/developer-portal/administration/application-registration/enable-key-auth-plugin.md new file mode 100644 index 000000000000..1d4d08f6da45 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/administration/application-registration/enable-key-auth-plugin.md @@ -0,0 +1,137 @@ +--- +title: Enable Key Authentication for Application Registration +badge: enterprise +--- + +You can use the Key Authentication plugin for authentication in conjunction with +the Application Registration plugin. + +The key auth plugin uses the same Client ID as generated for the Kong OAuth2 plugin. +You can use the same Client ID credential for a Service that has the OAuth2 plugin enabled. + +## Prerequisites + +* Create a Service. +* Enable the [Application Registration plugin](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration/) on a Service. +* Activate your application for a Service if you have not already done so. The +Service Contract must be approved by an Admin if auto approve is not enabled. +* [Generate a credential](#gen-client-id-cred) if you don't want to use the default credential initially created for you. + +## Enable Key Authentication in Kong Manager + +In Kong Manager, access the Service for which you want to enable key authentication for +use with application registration: + +1. From your Workspace, in the left navigation pane, go to **API Gateway > Services**. +2. On the Services page, select the Service and click **View**. +3. In the Plugins pane in the Services page, click **Add a Plugin**. +4. On the Add New Plugin page in the Authentication section, find the + **Key Authentication** Plugin and click **Enable**. + + ![Key Authentication plugin panel](/assets/images/products/gateway/dev-portal/key-auth-plugin-panel.png) + +5. Complete the fields as appropriate for your application. In this example, the Service is already + prepopulated. Refer to the parameters described in the next section, + [Key Authentication Configuration Parameters](#key-auth-params), + to complete the fields. + +6. Click **Create**. + +### Key Authentication Configuration Parameters {#key-auth-params} + +| Form Parameter | Description | +|:---------------|:----------------------------------------------------------------------------------| +| `Service` | The Service that this plugin configuration will target. Required. | +| `Anonymous` | An optional string (Consumer UUID) value to use as an anonymous Consumer if authentication fails. If empty (default), the request fails with an `4xx`. Note that this value must refer to the Consumer `id` attribute that is internal to Kong, and **not** its `custom_id`. | +| `Hide Credentials` | Whether to show or hide the credential from the Upstream service. If `true`, the plugin strips the credential from the request (i.e., the header, query string, or request body containing the key) before proxying it. Default: `false`. | +| `Key in Body` | If enabled, the plugin reads the request body (if said request has one and its MIME type is supported) and tries to find the key in it. Supported MIME types: `application/www-form-urlencoded`, `application/json`, and `multipart/form-data`. Default: `false`. | +| `Key in Header` | If enabled (default), the plugin reads the request header and tries to find the key in it. Default: true. | +| `Key in Query` | If enabled (default), the plugin reads the query parameter in the request and tries to find the key in it. Default: true. | +| `Key Names` | Describes an array of parameter names where the plugin will look for a key. The client must send the authentication key in one of those key names, and the plugin will try to read the credential from a header, request body, or query string parameter with the same name. The key names may only contain [a-z], [A-Z], [0-9], [_] underscore, and [-] hyphen. Required. Default: `apikey`. | +| `Run on Preflight` | Indicates whether the plugin should run (and try to authenticate) on `OPTIONS` preflight requests. Default: `true`. | + +## Generate a Credential {#gen-client-id-cred} + +Generate a Client ID credential to use as an API key. You can generate multiple +credentials. + +1. In the **Dev Portal > My Apps** page, click **View** for an application. + +2. In the **Authentication** pane, click **Generate Credential**. + + ![Application Authentication Pane](/assets/images/products/gateway/dev-portal/generate-cred-dev-portal.png) + + Now you can make requests using the Client ID as an API Key. + +## Make Requests with an API Key (Client Identifier) + +The Client ID of your credentials can be used as an API key to make authenticated requests to a Service. + +**Tip:** You can also access key request instructions directly within the user interface from the +information icon in the Services details area of your application. Click the **i** icon to open the Service Details page. + +![Services Pane](/assets/images/products/gateway/dev-portal/portal-info-modal-key-auth.png) + +Scroll to view all of the available examples. + +![Service Details Page Embedded Key Usage Instructions](/assets/images/products/gateway/dev-portal/service-details-key-auth-usage.png) + +### About API Key Locations in a Request + +{% include /md/plugins-hub/api-key-locations.md %} + +### Make a request with the key as a query string parameter + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -X POST {proxy}/{route}?apikey={CLIENT_ID} +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http {proxy}/{route}?apikey={CLIENT_ID} +``` +{% endnavtab %} +{% endnavtabs %} + +Response (will be the same for all valid requests regardless of key location): + +```bash +HTTP/1.1 200 OK +... +``` + +### Make a request with the key in a header + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -X POST {proxy}/{route} \ +--header "apikey: {CLIENT_ID}" +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http {proxy}/{route} apikey:{CLIENT_ID} +``` +{% endnavtab %} +{% endnavtabs %} + +### Make a request with the key in the body + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -X POST {proxy}/{route} \ +--data "apikey:={CLIENT_ID}" +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http {proxy}/{route} apikey={CLIENT_ID} +``` +{% endnavtab %} +{% endnavtabs %} + +**Note:** The `key_in_body` parameter must be set to `true`. diff --git a/app/gateway/2.7.x/developer-portal/administration/application-registration/managing-applications.md b/app/gateway/2.7.x/developer-portal/administration/application-registration/managing-applications.md new file mode 100644 index 000000000000..c66adb37ed2c --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/administration/application-registration/managing-applications.md @@ -0,0 +1,58 @@ +--- +title: Manage Applications +badge: enterprise +--- + +Developers can create applications from the Kong Dev Portal. An application can apply to any number of Services. This is called a Service Contract. To use an application with a Service, the Service Contract must have an Approved status. To enable automatic approval for all new Service Contracts, enable Auto-approve for the Portal Application Registration plugin. + +## Create an Application + +1. Log in to the Kong Dev Portal. +2. Click **My Apps** in the top navigation bar. +3. Click **New Application**. +4. Complete the **Create Application** dialog: + 1. Enter a unique `Application Name`. + 2. Enter a `Redirect URI`. + 3. Enter a `Description`. +5. Click **Create**. The Application Dashboard is displayed. From the +dashboard, you can view details about your application, view your credentials, +generate more credentials, and view your application status against a list of +Services. +6. Before you can use your application, you must activate it to create a Service +Contract for the Service. In the Services section of the Application Dashboard, +click **Activate** on the Service you want to use. If [Auto-approve](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration##aa) is not +enabled, your application will remain pending until an admin approves your +request. + +## View all Service Contracts for an Application + +A list of all applications in a Workspace can be accessed from the left navigation pane. + +1. Click **Applications** to view the list of applications. +2. From the Applications list, click an application to view all Service Contracts for the application; including contracts in Approved, Revoked, and Rejected status. +3. In the Service Contracts section, click the **Requested Access** tab to view Service Contracts requests for the application. Approve, revoke, or reject +requests. + +## View all Application Contracts for a Service + +View all Application Contracts and their status for a Service from the +**Service** page. + +1. Click **Services** in the left navigation pane. +2. Select the Service for which you have Application Registration enabled. +3. From the Service Contracts tab, view all Approved, Revoked, Rejected, and Requested Access for the Service. + +## Add a Document to your Service +When using Application Registration, it is recommended to link documentation +(OAS/Swagger spec) to your Service. Doing so allows Dev Portal users to easily +register Application Contracts for their applications from the documentation +page, and view a list of all documentation from the Catalog page. + +Add a document from the Service **View** page: +1. From your Workspace, in the left navigation pane, go to **API Gateway > Services**. +2. On the Services page, select the Service for which you want to add a document and click **View**. +3. In the Documents section, click **Add a Document**. +4. Choose a method to add the document to the Service: + - Use **Document Spec Path** to select an existing spec in the Portal. + - Use **Upload Document** to upload a new spec to the Portal. +5. Click **Add Document**. diff --git a/app/gateway/2.7.x/developer-portal/administration/application-registration/okta-config.md b/app/gateway/2.7.x/developer-portal/administration/application-registration/okta-config.md new file mode 100644 index 000000000000..34ad21f248ca --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/administration/application-registration/okta-config.md @@ -0,0 +1,108 @@ +--- +title: Set Up External Portal Application Authentication with Okta and OIDC +badge: enterprise +--- + +These instructions help you set up Okta as your third-party identity provider +for use with the Kong OIDC and Portal Application Registration plugins. + +## Define an authorization server and create a custom claim in Okta {#auth-server-cclaim} + +Follow these steps to set up an authorization server in Okta for all authorization types. + +1. Sign in to the [Developer Okta site](https://developer.okta.com/). +1. Click **Security > API > Authorization Servers**. + + Notice that you already have an authorization server set up named `default`. + This example uses the default auth server. You can also create as many + custom authorization servers as necessary to fulfill your requirements. For + more information, refer to the + [Okta developer documentation](https://developer.okta.com/docs/guides/customize-authz-server/overview/). + +2. Click **default** to view the details for the default auth server. Take note +of the `Issuer` URL, which you will use to associate Kong with your authorization server. + +1. Click the **Claims** tab. + +2. Click **Add Claim**. Add a custom claim called `application_id` that will attach any successfully authenticated application's `id` to the access token. + 1. Enter `application_id` in the **Name** field. + 2. Ensure the `Include in token type` selection is **Access Token**. + 3. Enter `app.clientId` in the **Value** field. + 4. Click **Create**. + + Now that you have created a custom claim, you can associate the `client_id` + with a Service via the Application Registration plugin. Start by creating a Service in Kong Manager. + +3. Create a Service and a Route and instantiate an OIDC plugin on that Service. + You can allow most options to use their defaults. + + 1. In the `Config.Issuer` field, enter the Issuer URL of the Authorization server from your identity provider. + + ![OIDC with Okta Issuer URL](/assets/images/products/gateway/dev-portal/oidc-issuer-url.png) + + 2. In the `Config.Consumer Claim` field, enter the name of the field from the Okta payload that contains the application ID. + This is usually `sub`. + + **Tip:** Because Okta's discovery document does not include all supported + auth types by default, ensure the + `config.verify_parameters` option is disabled. + + ![Clear Config Verify Parameters for OIDC with Okta](/assets/images/products/gateway/dev-portal/oidc-clear-verify-params-app-reg.png) + + The core configuration should be: + + ```json + { + "issuer": "", + "verify_credentials": false, + "consumer_claim": "sub", + } + + ``` + +4. Configure a Portal Application Registration plugin on the Service as well. See +[Application Registration](/gateway/{{page.release}}/developer-portal/administration/application-registration/enable-application-registration#config-app-reg-plugin). + +## Register an application in Okta + +Follow these steps to register an application in Okta and associate the Okta +application with an application in the Kong Dev Portal. + +1. Sign in to the [Developer Okta site](https://developer.okta.com/). +2. Click **Applications** > **Applications**. +3. Depending on which authentication flow you want to implement, the setup of +your Okta application will vary: + + - **Create a new app integration**: Select `API Services` when prompted for an application type. In the **New API Services App Integration** modal, enter your app integration name. + + You will need your `client_id` and `client_secret` later on when you [authenticate with the proxy](/gateway/{{page.release}}/developer-portal/administration/application-registration/3rd-party-oauth#cc-flow). + + - **Implicit Grant**: Select `Single-Page App`, `Native`, or `Web` when + prompted for an application type. Make sure `Implicit` is selected for + `Allowed grant types`. Enter the `Login redirect URIs`, `Logout redirect URIs`, and `Initiate login URI` fields with the correct values, depending on your application's routing. The Implicit Grant flow is not recommended if the Authorization Code flow is possible. + + - **Authorization Code**: Select `Single-Page App`, `Native`, or `Web` when + prompted for an application type. Make sure `Authorization Code` is selected for `Allowed grant types`. Enter the `Login redirect URIs`, `Logout redirect URIs`, and `Initiate login URI` fields with the correct values, depending on your application's routing. + +## Associate the identity provider application with your Kong application + +Now that the application has been configured in Okta, you need to associate the +Okta application with the corresponding application in Kong's Dev Portal. + +{:.note} +> **Note:** Each developer should have their own application in both Okta and Kong. +Each Okta application has its own `client_id` that maps to its respective application in Kong. +Essentially, this maps identity provider applications to portal applications. + +This example assumes Client Credentials is the chosen OAuth flow. + +1. In the Kong Dev Portal, create an account if you haven't already. +2. After you've logged in, click `My Apps`. +3. On the Applications page, click `+ New Application`. +4. Complete the **Name** and **Description** fields. Paste the `client_id` of your corresponding Okta (or other identity provider) application into the **Reference Id** field. + + ![Kong Create Application with Reference Id](/assets/images/products/gateway/dev-portal/create-app-ref-id.png) + +Now that the application has been created, developers can authenticate with the +endpoint using the supported and recommended +[third-party OAuth flows](/gateway/{{page.release}}/developer-portal/administration/application-registration/3rd-party-oauth). diff --git a/app/gateway/2.7.x/developer-portal/administration/developer-permissions.md b/app/gateway/2.7.x/developer-portal/administration/developer-permissions.md new file mode 100644 index 000000000000..bbd41e4dd296 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/administration/developer-permissions.md @@ -0,0 +1,87 @@ +--- +title: Developer Roles and Content Permissions +badge: enterprise +--- + +Access to the Dev Portal can be fine-tuned with the use of Developer +Roles and Content Permissions, managed through the Dev Portal Permissions page +of Kong Manager. This page can be found by clicking the **Permissions** link +under **Dev Portal** in the Kong Manager navigation bar. + +## Roles + +The Roles Tab contains a list of available developer roles as well as providing +the ability to create and edit roles. + +Selecting Create Role allows you to enter a unique role name, as well as a +comment to provide context for the nature of the role. You can assign the role +to existing developers from within the role creation page. Clicking Create +saves the role and returns you to the Roles List view. There you can see your +newly created role as well as any other previously defined roles. + +Clicking View displays the Role Details page with a list of developers assigned. + +From the Role Details page, click the Edit button to make changes to the role. You can also access this page from the Roles List Edit button. Here you can change the name and comment of the role, assign or remove developers, or delete the role. + +Deleting a role will remove it from any developers assigned the role and remove +the role restriction from any content files it is applied to. + +## Content + +The Content Tab shows the list of content files used by the Dev Portal. You can +apply roles to your content files, restricting access only to developers who +possess certain roles. Selecting an individual content file displays a +dropdown of available developer roles where you can choose which role has +access to the file. Unchecking all available roles will leave the file +unauthenticated. + +An additional option, the `*` role, is preset in the list. This predefined role +behaves differently from other roles. When a content file has the `*` role +attached to it, any developer may view the page as long as they are +authenticated. Additionally, the `*` role may not be used in conjunction with +other user-defined roles and will deselect those roles when `*` is selected. + +{:.important} +> **Important:** The `dashboard.txt` and `settings.txt` content files are +assigned the `*` role by default. All other content files have no roles by +default. This means that until a role is added, the file is unauthenticated +even if Dev Portal Authentication is enabled. Content Permissions are ignored +when Dev Portal Authentication is disabled. + +## `readable_by` attribute + +When a role is applied to a content file using the Content Tab, a special +attribute `readable_by` is added to the headmatter of the file. + +``` +--- +readable_by: + - role_name + - another_role_name +--- +``` + + In the case of spec files, `readable_by` is applied under the key `x-headmatter` or `X-headmatter`. + +``` +x-headmatter: + readable_by: + - role_name + - another_role_name +``` + +The value of `readable_by` is an array of string role names that have access to +view the content file. An exception is when the `*` role is applied to the +file. In this case, the value of `readable_by` is no longer an array, because +it contains the single string character `*`. + +``` +readable_by: "*" +``` + +⚠️**Important:** If you manually remove or edit the `readable_by` attribute, it +will modify the permissions of the file. Attempting to save a content file with +a `readable_by` array containing a nonexistent role name will result in an +error. Additionally, if you make changes to permissions in the Content Tab or +the Portal Editor, be sure to sync any local files so that permissions are not +overwritten the next time you push changes. diff --git a/app/gateway/2.7.x/developer-portal/administration/managing-developers.md b/app/gateway/2.7.x/developer-portal/administration/managing-developers.md new file mode 100644 index 000000000000..87e8b5b4732c --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/administration/managing-developers.md @@ -0,0 +1,133 @@ +--- +title: Managing Developers +badge: enterprise +--- + +## Developer Status + +A status represents the state of a developer and the access they have to the Dev + Portal and APIs: + +* **Approved** + * A developer who can access the Dev Portal. Approved developers can create + credentials & access **all** APIs that allow those credentials. +* **Requested** + * A developer who has requested access but has not yet been Approved. +* **Rejected** + * A developer who has had their request denied by a Kong admin. +* **Revoked** + * A developer who once had access to the Dev Portal but has since had access + Revoked. + +## Approving Developers + +Developers who have requested access to a Dev Portal will appear under the +**Requested Access** tab. From this tab, you can choose to *Accept* or *Reject* +the developer from the actions in the table row. After selecting an action, the +corresponding tab is updated. + +## View Approved Developers + +To view all currently approved developers, click the **Approved** tab. From here, you can choose to *Revoke* or *Delete* a particular developer. Additionally, you can use this view to send an email to a developer with the **Email Developer** `mailto` link. See [Emailing Developers](#emailing-developers) for more info. + +## View Revoked Developers + +To view all currently revoked developers, click the **Revoked** tab. From here, you can choose to *Re-approve* or *Delete* a developer. + +### View Rejected Developers + +To view all currently rejected developers, click the **Rejected** tab. Rejected developers completed the registration flow on your Dev Portal but were rejected from the **Request Access** tab. You may *Approve* or *Delete* a developer from this tab. + +## Email Developers + +### Invite Developers to Register + +To invite a single or multiple developers: + +1. Click **Invite Developers**. +2. Use the popup modal to enter email addresses separated by commas. +3. After all emails have been added, click **Invite**. A pre-filled message +opens in your default email client with a link to the registration page for +your Dev Portal. + +Each developer is bcc'd by default for privacy. You may choose to edit the message or send as is. + +## Developer Management Property Reference + + + +### portal_auto_approve + +**Default:** `off` + +**Description:** +Dev Portal Auto Approve Access. + +When set to `on`, a developer will automatically be marked as `approved` after +completing Dev Portal registration. Access can still be revoked through +Kong Manager or the API. + +When set to `off`, a Kong admin will have to manually approve the Developer +using Kong Manager or the API. + +### portal_invite_email + +**Default:** `on` + +**Description:** +When enabled, Kong admins can invite developers to a Dev Portal by using +the Invite button in Kong Manager. + +### portal_access_request_email + +**Default:** `on` + +**Description:** +When enabled, Kong admins specified by `smtp_admin_emails` will receive an email +when a developer requests access to a Dev Portal. + +When disabled, Kong admins will have to manually check the Kong Manager to view +any requests. + +### portal_approved_email + +**Default:** `on` + +**Description:** +When enabled, developers will receive an email when access to a Dev Portal has +been approved. + +When disabled, developers will receive no indication that they have been +approved. It is suggested to only disable this feature if `portal_auto_approve` +is enabled. + +### portal_reset_email + +**Default:** `on` + +**Description:** +When enabled, developers will be able to use the Reset Password flow on a Dev +Portal and will receive an email with password reset instructions. + +When disabled, developers will *not* be able to reset their account passwords. +Kong Admins will have to manually create new credentials for the Developer in +the Kong Manager. + +### portal_token_exp + +**Default:** `21600` + +**Description:** +Duration in seconds for the expiration of the Dev Portal reset password token. +Default is `21600` (six hours). + +### portal_reset_success_email + +**Default:** `on` + +**Description:** +When enabled, developers will receive an email after successfully resetting +their Dev Portal account password. + +When disabled, developers will still be able to reset their account passwords, +but will not receive a confirmation email. diff --git a/app/gateway/2.7.x/developer-portal/configuration/authentication/adding-registration-fields.md b/app/gateway/2.7.x/developer-portal/configuration/authentication/adding-registration-fields.md new file mode 100644 index 000000000000..9488632184f0 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/configuration/authentication/adding-registration-fields.md @@ -0,0 +1,24 @@ +--- +title: Adding Dev Portal Registration Fields +badge: enterprise +--- + +When authentication is enabled for a Dev Portal, the only required +fields by default are **full name**, **email**, and **password**. However, you +can add custom fields to this form and indicate whether the fields are +required. Adding custom required fields will not affect existing registered +users until they choose to edit their profile. + +### Adding Custom Registration Fields + +1. In Kong Manager, navigate to the Workspace's Dev Portal **Settings** page. + +2. Click the **Developer Meta Fields** tab. + +3. Click **+ Add Field** to add a new field object to the form. + +4. Enter a label, field name, and select the type of input. + +5. Select the **Required** checkbox to require the new field for registration. + +6. Click **Save Changes**. The field is automatically added to the registration form. diff --git a/app/gateway/2.7.x/developer-portal/configuration/authentication/basic-auth.md b/app/gateway/2.7.x/developer-portal/configuration/authentication/basic-auth.md new file mode 100644 index 000000000000..5b9eb10095f9 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/configuration/authentication/basic-auth.md @@ -0,0 +1,82 @@ +--- +title: Enable Basic Auth in the Dev Portal +badge: enterprise +--- + +The Kong Dev Portal can be fully or partially authenticated using HTTP protocol's Basic Authentication scheme. Requests are sent with an Authorization header that +contains the word `Basic` followed by the base64-encoded `username:password` string. + +Basic Authentication for the Dev Portal can be enabled using any of the following ways: + +- [Enable Portal Session Config](#enable-portal-session-config) +- [Enable Basic Auth Using Kong Manager](#enable-basic-auth-using-kong-manager) +- [Enable Basic Auth Using the Command Line](#enable-basic-auth-using-the-command-line) +- [Enable Basic Auth Using `kong.conf`](#enable-basic-auth-using-kongconf) + +**Warnings:** + +- Enabling authentication in the Dev Portal requires use of the +Sessions plugin. Developers will not be able to log in if this is not properly set. +For more information, see +[Sessions in the Dev Portal](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions). + +- When Dev Portal Authentication is enabled, content files remain unauthenticated until a role is applied to them. The exceptions are `settings.txt` and `dashboard.txt`, which begin with the `*` role. For more information, see +[Developer Roles and Content Permissions](/gateway/{{page.release}}/developer-portal/administration/developer-permissions). + +## Enable Portal Session Config + +In the Kong configuration file, set the `portal_session_conf` property: + +``` +portal_session_conf={ "cookie_name":"portal_session","secret":"","storage":"kong"} +``` + +If using HTTP while testing, include `"cookie_secure": false` in the config: + +``` +portal_session_conf={ "cookie_name":"portal_session","secret":"","storage":"kong","cookie_secure":false} +``` + +Or, if you have different subdomains for the `portal_api_url` and `portal_gui_host`, set the `cookie_domain` +and `cookie_samesite` properties as follows: + +``` +portal_session_conf={ "cookie_name":"portal_session","secret":"","storage":"kong","cookie_secure":false,"cookie_domain":"<.your_subdomain.com>","cookie_samesite":"off" } +``` + +See also: + +- For more information about portal session configuration, see +[Sessions](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions#portal-session-conf). + +- For more information about domains and cookies in Dev Portal sessions, see +[Domains](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions#domains). + +## Enable Basic Auth Using Kong Manager + +1. Navigate to the Dev Portal's **Settings** page. +1. Find **Authentication plugin** under the **Authentication** tab. +1. Select **Basic Authentication**. +1. Click **Save Changes**. + +## Enable Basic Auth Using the Command Line + +To patch a Dev Portal's authentication property directly, run: + +```bash +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal_auth=basic-auth" +``` + +## Enable Basic Auth Using `kong.conf` + +Kong allows for a default authentication plugin to be set in the Kong +configuration file with the `portal_auth` property. + +In your `kong.conf` file, set the property as follows: + +``` +portal_auth="basic-auth" +``` + +This sets all Dev Portals to use Basic Authentication by default when initialized. diff --git a/app/gateway/2.7.x/developer-portal/configuration/authentication/key-auth.md b/app/gateway/2.7.x/developer-portal/configuration/authentication/key-auth.md new file mode 100644 index 000000000000..dd68c2b7940b --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/configuration/authentication/key-auth.md @@ -0,0 +1,64 @@ +--- +title: Enable Key Auth in the Dev Portal +badge: enterprise +--- + +The Kong Dev Portal can be fully or partially authenticated using API keys or **Key +Authentication**. Users provide a unique key upon registering and use this key +to log into the Dev Portal. + +Key Authentication for the Dev Portal can be enabled in three ways: + +- via the [Kong Manager](#enable-key-auth-via-kong-manager) +- via the [command line](#enable-key-auth-via-the-command-line) +- via the [Kong configuration file](#enable-key-auth-via-the-kongconf) + +>**Warning** Enabling authentication in the Dev Portal requires use of the +> Sessions plugin. Developers will not be able to login if this is not set +> properly. More information about [Sessions in the Dev Portal](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions/) + +## Enable Portal Session Config + +``` +portal_session_conf={ "cookie_name": "portal_session", "secret": "CHANGE_THIS", "storage": "kong" } +``` + +If using HTTP while testing, include `"cookie_secure": false` in the config: + +``` +portal_session_conf={ "cookie_name": "portal_session", "secret": "CHANGE_THIS", "storage": "kong", "cookie_secure": false } +``` + +## Enable Key Auth via Kong Manager + +1. Navigate to the Dev Portal's **Settings** page. +2. Find **Authentication plugin** under the **Authentication** tab. +3. Select **Key Authentication** from the drop down. +4. Click **Save Changes**. + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +## Enable Key Auth via the Command Line + +To patch a Dev Portal's authentication property directly, run: + +``` +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal_auth=key-auth" +``` + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +## Enable Key Auth via the Kong.conf + +Kong allows for a `default authentication plugin` to be set in the Kong +configuration file with the `portal_auth` property. + +In your `kong.conf` file, set the property as follows: + +``` +portal_auth="key-auth" +``` + +This will set every Dev Portal to use Key Authentication by default when +initialized, regardless of Workspace. diff --git a/app/gateway/2.7.x/developer-portal/configuration/authentication/oidc.md b/app/gateway/2.7.x/developer-portal/configuration/authentication/oidc.md new file mode 100644 index 000000000000..d40bca4ce1c8 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/configuration/authentication/oidc.md @@ -0,0 +1,146 @@ +--- +title: Enable OpenID Connect in the Dev Portal +badge: enterprise +--- + +The [OpenID Connect Plugin](/hub/kong-inc/openid-connect/) (OIDC) +allows the Kong Dev Portal to hook into existing authentication setups using third-party +*Identity Providers* (IdP) such as Google, Okta, Microsoft Azure AD, +[Curity](/gateway/{{page.release}}/configure/auth/oidc-curity/#kong-dev-portal-authentication), etc. + +[OIDC](/hub/kong-inc/openid-connect/) must be used with +the `session` method, utilizing cookies for Dev Portal File API requests. + +In addition, a configuration object is required to enable OIDC. Refer to the +[Sample Configuration Object](#/sample-configuration-object) section of this +document for more information. + +{:.note} +> **Note**: The Dev Portal does not automatically create developer accounts on login via OIDC. +A developer account matching the `consumer_claim` configuration parameter has to be +created and approved (if auto approve is not enabled) beforehand. +>

    +> During the registration flow, users must enter their login information in their +IDP-redirected login page. The user is then brought to the Dev Portal +registration page and their email is pre-populated in the registration form. +Users cannot change their email in the registration form. +The user may be asked for additional fields, as set by the account admin. + +OIDC for the Dev Portal can be enabled in one of the following ways: + +- [Portal Session Plugin Config](#portal-session-plugin-config) +- [Sample Configuration Object](#sample-configuration-object) +- [Enable OIDC using Kong Manager](#enable-oidc-using-kong-manager) +- [Enable OIDC using the Command Line](#enable-oidc-using-the-command-line) +- [Enable OIDC using kong.conf](#enable-oidc-using-kongconf) + +## Portal Session Plugin Config + +Session Plugin Config does not apply when using OpenID Connect. + +## Sample Configuration Object + +Below is a sample configuration JSON object for using *Google* as the Identity +Provider: + +``` +{ + "consumer_by": ["username","custom_id","id"], + "leeway": 1000, + "scopes": ["openid","profile","email","offline_access"], + "logout_query_arg": "logout", + "client_id": [""], + "login_action": "redirect", + "logout_redirect_uri": ["http://localhost:8003"], + "ssl_verify": false, + "consumer_claim": ["email"], + "forbidden_redirect_uri": ["http://localhost:8003/unauthorized"], + "client_secret": [""], + "issuer": "https://accounts.google.com/", + "logout_methods": ["GET"], + "login_redirect_uri": ["http://localhost:8003"], + "login_redirect_mode": "query" +} +``` + +The placeholders above should be replaced with your actual values: + + - `` - Client ID provided by IdP + - `` - Client secret provided by IdP + +See the [documentation of the OpenID Connect plugin](/hub/kong-inc/openid-connect/) +for more information. + +**Important:** The `redirect_uri` needs to be configured as an allowed URI in the IdP. +If not set explicitly in the configuration object, the URI default is +`http://localhost:8004//auth`. + +If `portal_gui_host` and `portal_api_url` are set to share a domain but differ +with regard to subdomain, `redirect_uri` and `session_cookie_domain` need to be +configured to allow OpenID Connect to apply the session correctly. + +Example: + +``` +{ + "consumer_by": ["username","custom_id","id"], + "leeway": 1000, + "scopes": ["openid","profile","email","offline_access"], + "logout_query_arg": "logout", + "client_id": [""], + "login_redirect_uri": ["https://example.portal.com"], + "login_action": "redirect", + "logout_redirect_uri": ["https://example.portal.com"], + "ssl_verify": false, + "consumer_claim": ["email"], + "redirect_uri": ["https://exampleapi.portal.com/auth"], + "session_cookie_domain": ".portal.com", + "forbidden_redirect_uri": ["https://example.portal.com/unauthorized"], + "client_secret": ["**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +## Enable OIDC using the Command Line + +You can use the Kong Admin API to set up Dev Portal Authentication. +To patch a Dev Portal's authentication property directly, run: + +``` +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal_auth=openid-connect" + "config.portal_auth_conf= +``` + +>**Warning** When Dev Portal Authentication is enabled, content files will remain unauthenticated until a role is applied to them. The exception to this is `settings.txt` and `dashboard.txt` which begin with the `*` role. Please visit the Developer Roles and Content Permissions section for more info. + +## Enable OIDC using kong.conf + +Kong allows for a `default authentication plugin` to be set in the Kong +configuration file with the `portal_auth` property. + +In your `kong.conf` file, set the property as follows: + +``` +portal_auth="openid-connect" +``` + +Then set the `portal_auth_conf` property to your +customized [**Configuration JSON Object**](#sample-configuration-object). + +This will set every Dev Portal to use OIDC by default when initialized, regardless of Workspace. diff --git a/app/gateway/2.7.x/developer-portal/configuration/authentication/sessions.md b/app/gateway/2.7.x/developer-portal/configuration/authentication/sessions.md new file mode 100644 index 000000000000..3d7e4260006d --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/configuration/authentication/sessions.md @@ -0,0 +1,116 @@ +--- +title: Sessions in the Dev Portal +--- + +{:.important} +> **Important**: Portal Session Configuration does not apply when using [OpenID Connect](/hub/kong-inc/openid-connect/) for Dev Portal authentication. The following information assumes that the Dev Portal is configured with `portal_auth` other than `openid-connect`; for example, `key-auth` or `basic-auth`. + +## How does the Sessions Plugin work in the Dev Portal? + +When a user logs in to the Dev Portal with their credentials, the Sessions Plugin will create a session cookie. The cookie is used for all subsequent requests and is valid to authenticate the user. The session has a limited duration and renews at a configurable interval, which helps prevent an attacker from obtaining and using a stale cookie after the session has ended. + +The Session configuration is secure by default, which may [require alteration](#session-security) if using HTTP or different domains for [`portal_api_url`](/gateway/{{page.release}}/reference/configuration/#portal_api_url) and [`portal_gui_host`](/gateway/{{page.release}}/reference/configuration/#portal_gui_host). Even if an attacker were to obtain a stale cookie, it would not benefit them since the cookie is encrypted. The encrypted session data may be stored either in Kong or the cookie itself. + +## Configuration to Use the Sessions Plugin with the Dev Portal + +To enable sessions authentication, configure the following: + +``` +portal_auth = +portal_session_conf = { + "secret":"", + "cookie_name":"", + "storage":"kong", + "cookie_lifetime":, + "cookie_renew":, + "cookie_secure":, + "cookie_domain":"", + "cookie_samesite":"" +} +``` + +* `"cookie_name":""`: The name of the cookie + * For example, `"cookie_name":"portal_cookie"` +* `"secret":""`: The secret used in keyed HMAC generation. Although + the **Session Plugin's** default is a random string, the `secret` _must_ be + manually set for use with the Dev Portal since it must be the same across all + Kong workers/nodes. +* `"storage":"kong"`: Where session data is stored. This value _must_ be set to `kong` for use with the Dev Portal. +* `"cookie_lifetime":`: The duration (in seconds) that the session will remain open; 3600 by default. +* `"cookie_renew":`: The duration (in seconds) of a session remaining at which point + the Plugin renews the session; 600 by default. +* `"cookie_secure":`: `true` by default. See [Session Security](#session-security) for + exceptions. +* `"cookie_domain"::` Optional. See [Session Security](#session-security) for exceptions. +* `"cookie_samesite":""`: `"Strict"` by default. See [Session Security](#session-security) for + exceptions. + +⚠️**Important:** +*The following properties must not be altered from default for use with the Dev Portal:* +* `logout_methods` +* `logout_query_arg` +* `logout_post_arg` + +For detailed descriptions of each configuration property, see the [Session Plugin documentation](/hub/kong-inc/session/). + +## Session Security + +The Session configuration is secure by default, so the cookie uses the [Secure, HttpOnly](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies), and [SameSite](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies) directives. + +⚠️**Important:** The following properties must be altered depending on the protocol and domains in use: +* If using HTTP instead of HTTPS: `"cookie_secure": false` +* If using different subdomains for the [`portal_api_url`](/gateway/{{page.release}}/reference/configuration/#portal_api_url) and [`portal_gui_host`](/gateway/{{page.release}}/reference/configuration/#portal_gui_host), see the example below for [Domains](/gateway/{{page.release}}/developer-portal/configuration/authentication/sessions/#domains). + +{:.important} +> **Important:** Sessions are not invalidated when a user logs out if `"storage": "cookie"` +(the default) is used. In that case, the cookie is deleted client-side. Only when session data is +stored server-side with `"storage": "kong"` set is the session actively invalidated. + +## Example Configurations + +### HTTPS with the same domain for API and GUI + +If using HTTPS and hosting Dev Portal API and the Dev Portal GUI from the same domain, the following configuration could be used for Basic Auth: + +``` +portal_auth = basic-auth +portal_session_conf = { + "cookie_name":"$4m04$" + "secret":"change-this-secret" + "storage":"kong" + "cookie_secure":true +} +``` + +In testing, if using HTTP, the following configuration could be used instead: + +``` +portal_auth = basic-auth +portal_session_conf = { + "cookie_name":"04tm34l" + "secret":"change-this-secret" + "storage":"kong" + "cookie_secure":false +} +``` + +### Domains + +The dev portal `portal_gui_host` and the dev +portal api `portal_api_url` must share a domain or subdomain. The following +example assumes subdomains of `portal.xyz.com` and `portalapi.xyz.com`. +Set a subdomain such as ``"cookie_domain": ".xyz.com"`` and set +`cookie_samesite` to `off`. + +``` +portal_auth = basic-auth +portal_session_conf = { + "storage":"kong" + "cookie_name":"portal_session" + "cookie_domain": ".xyz.com" + "secret":"super-secret" + "cookie_secure":false + "cookie_lifetime":31557600, + "cookie_samesite":"off" +} +``` diff --git a/app/gateway/2.7.x/developer-portal/configuration/smtp.md b/app/gateway/2.7.x/developer-portal/configuration/smtp.md new file mode 100644 index 000000000000..983f009dd58f --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/configuration/smtp.md @@ -0,0 +1,151 @@ +--- +title: Dev Portal SMTP Configuration +badge: enterprise +--- + +The following property reference outlines each email and email variable used by the Dev Portal to send emails to Kong admins and developers. + +These settings can be modified in the `Kong Manager` under the Dev Portal `Settings / Email` tab, or by running the following command: + +``` +curl http://localhost:8001/workspaces/ \ + --data "config.=off" +``` + +If they are not modified manually, the Dev Portal will use the default value defined in the Kong Configuration file. + +Dev Portal email content and styling can be customized via [template files](/gateway/{{page.release}}/developer-portal/theme-customization/emails/). + + + +## portal_invite_email + +**Default:** `on` + +**Description:** +When enabled, Kong admins will be able to invite developers to a Dev Portal by using the Invite button in the Kong Manager. + +**Email:** +``` +Subject: Invite to access Dev Portal + +Hello Developer! + +You have been invited to create a Dev Portal account at %s. +Please visit `` to create your account. +``` + + +## portal_email_verification + +**Default:** `off` + +**Description:** +When enabled, developers will receive an email upon registration to verify their account. Developers will not be able to use the Dev Portal until their account is verified, even if auto-approve is enabled. + + +## portal_access_request_email + +**Default:** `on` + +**Description:** +When enabled, Kong Admins specified by `smtp_admin_emails` will receive an email when a Developer requests access to a Dev Portal. + +``` +Subject: Request to access Dev Portal + +Hello Admin! + + has requested Dev Portal access for . +Please visit to review this request. +``` + + +## portal_approved_email + +**Default:** `on` + +**Description:** +When enabled, developers will receive an email when access to a Dev Portal has been approved. + +``` +Subject: Dev Portal access approved + +Hello Developer! +You have been approved to access . +Please visit to login. + +``` + +## portal_reset_email + +**Default:** `on` + +**Description:** +When enabled, developers will be able to use the Reset Password flow on a Dev Portal and will receive an email with password reset instructions. + +When disabled, developers will *not* be able to reset their account passwords. + +``` +Subject: Password Reset Instructions for Dev Portal . + +Hello Developer, + +Please click the link below to reset your Dev Portal password. + + + +This link will expire in + +If you didn't make this request, keep your account secure by clicking +the link above to change your password. +``` + +## portal_reset_success_email + +**Default:** `on` + +**Description:** +When enabled, developers will receive an email after successfully resetting their Dev Portal account password. + +When disabled, developers will still be able to reset their account passwords, but will not receive a confirmation email. + +``` +Subject: Dev Portal password change success + +Hello Developer, +We are emailing you to let you know that your Dev Portal password at has been changed. + +Click the link below to sign in with your new credentials. + + +``` + + +## portal_emails_from + +**Default:** `nil` + +**Description:** +The name and email address for the 'From' header included in all Dev Portal emails. + +**Example :** + +``` +portal_emails_from = Your Name +``` + + +## portal_emails_reply_to + +**Default:** `nil` + +**Description:** +The email address for the 'Reply-To' header included in all Dev Portal emails. + + +**Example :** + +``` +portal_emails_reply_to: noreply@example.com +``` diff --git a/app/gateway/2.7.x/developer-portal/configuration/workspaces.md b/app/gateway/2.7.x/developer-portal/configuration/workspaces.md new file mode 100644 index 000000000000..2eacaeb0116e --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/configuration/workspaces.md @@ -0,0 +1,79 @@ +--- +title: Running Multiple Dev Portals with Workspaces +badge: enterprise +--- + +Kong supports running multiple instances of the Dev Portal with the use of +[**Workspaces**](/gateway/{{page.release}}/admin-api/workspaces/reference). This allows each Workspace to enable +and maintain separate Dev Portals (complete with separate files, settings, and +authorization) from within a single instance of Kong. + +## Manage Multiple Dev Portals within Kong Manager + +A snapshot of every Dev Portal within an instance of Kong can be viewed via +the Kong Manager's **Dev Portals** top navigation tab. + +This page details: + +- Whether a Dev Portal in a given Workspace is enabled or disabled +- A link to set up the Dev Portal if it is not enabled +- A link to each Dev Portal's homepage +- A link to each Dev Portal's individual overview page within Kong Manager +- Whether or not each Dev Portal is authenticated (indicated by a lock icon +in the upper right corner of each card) + +## Enable a Workspace's Dev Portal + +As with the **default** Workspace, when an additional Workspace is created, +its associated Dev Portal is `disabled` until it's manually enabled. + +This can be done from the Kong Manager by clicking the **Set up Dev Portal** +button located on the **Dev Portals** Overview page, or by navigating directly +to a Workspace's **Dev Portal Settings** page via the sidebar and toggling the +`Dev Portal Switch`, or by sending the following cURL request: + +```bash +curl -X PATCH http://localhost:8001/workspaces/ \ + --data "config.portal=true" +``` + +On initialization, Kong will populate the new Dev Portal with the [**Default Settings**](/gateway/{{page.release}}/reference/configuration/#dev-portal) defined in Kong's configuration file. + +>*Note* A Workspace can only enable a Dev Portal if the Dev Portal feature has been enabled in Kong's configuration. + + +## Define the Dev Portal's URL structure + +The URL of each Dev Portal is automatically configured on initialization and +is determined by four properties: + +1. The `portal_gui_protocol` property +2. The `portal_gui_host` property +3. Whether the `portal_gui_use_subdomains` property is enabled or disabled +4. The `name` of the Workspace + +Example URL with subdomains disabled: `http://localhost:8003/example-workspace` + +Example URL with subdomains enabled: `http://example-workspace.localhost:8003` + +The first three properties are controlled by Kong's configuration file and +cannot be edited via the Kong Manager. + +## Override Default Settings + +On initialization, the Dev Portal will be configured using the [**Default Portal Settings**](/gateway/{{page.release}}/reference/configuration/#dev-portal) defined in Kong's configuration file. + +{:.note} +> **Note**: You can only enable a Dev Portal for a Workspace if the +Dev Portal feature has been [enabled for {{site.base_gateway}}](/gateway/{{page.release}}/developer-portal/enable-dev-portal/). + +These settings can be manually overridden in the Dev Portals **Settings** tab +in the Kong Manager or by patching the setting directly. + +## Workspace Files + +On initialization of a Workspace's Dev Portal, a copy of the **default** Dev Portal files will be made and inserted into the new Dev Portal. This allows for the easy transference of a customized Dev Portal theme and allows **default** to act as a 'master template' -- however, the Dev Portal will not continue to sync changes from the **default** Dev Portal after it is first enabled. + +## Developer Access + +Access is not synced between Dev Portals. If an Admin or Developer wants access to multiple Dev Portals, they must sign up for each Dev Portal individually. diff --git a/app/gateway/2.7.x/developer-portal/enable-dev-portal.md b/app/gateway/2.7.x/developer-portal/enable-dev-portal.md new file mode 100644 index 000000000000..77f6c69894fb --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/enable-dev-portal.md @@ -0,0 +1,66 @@ +--- +title: How To Enable the Dev Portal +badge: enterprise +--- + +Enable Dev Portal in the Kong Configuration or within a Docker container for Docker installations. + +## Enable Dev Portal in the Kong Configuration + +1. To enable the Dev Portal, the following properties must be set in the Kong +configuration file (`kong.conf`): + + ```bash + portal = on + ``` + + {{site.base_gateway}} must be **restarted** for this value to take effect. + +2. Enable the default Workspace Dev Portal via Kong Manager: + + 1. Navigate to the default Workspace in Kong Manager + 2. Click the **Settings** link under **Dev Portal** + 3. Toggle the **Dev Portal Switch** + + It may take a few seconds for the Settings page to populate. + + To enable the default Workspace's Dev portal via the command line: + + ```bash + curl -X PATCH http://localhost:8001/workspaces/default --data "config.portal=true" + ``` + + - This will expose the **default Dev Portal** at [http://localhost:8003/default](http://localhost:8003/default) + - The **Dev Portal Files endpoint** can be accessed at `:8001/files` + - The **Public Dev Portal Files API** can be accessed at `:8004/files` + +## Enable Dev Portal with Docker installation + +{:.note} +> This feature is only available with a [{{site.konnect_product_name}} Enterprise](/gateway/{{page.release}}/plan-and-deploy/licenses/) subscription. + +1. [Deploy a license](/gateway/{{page.release}}/plan-and-deploy/licenses/deploy-license/). + +2. In your Docker container, set the Portal URL and set `KONG_PORTAL` to `on`: + + ```plaintext + echo "KONG_PORTAL_GUI_HOST=localhost:8003 KONG_PORTAL=on kong reload exit" \ + | docker exec -i kong /bin/sh + ``` + + {:.note} + > The `HOSTNAME` for `KONG_PORTAL_GUI_HOST` should not be preceded by a protocol, for example, `http://`. + +3. Execute the following command: + + ```sh + curl -X PATCH --url http://localhost:8001/workspaces/default \ + --data "config.portal=true" + ``` + +4. Access the Dev Portal for the default workspace using the URL specified +in the `KONG_PORTAL_GUI_HOST` variable: + + ```sh + http://localhost:8003/default + ``` diff --git a/app/gateway/2.7.x/developer-portal/helpers/cli.md b/app/gateway/2.7.x/developer-portal/helpers/cli.md new file mode 100644 index 000000000000..7fe10c224d76 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/helpers/cli.md @@ -0,0 +1,70 @@ +--- +title: Developer Portal CLI +badge: enterprise +--- + +The Kong Developer Portal CLI is used to manage your Developer Portals from the +command line. It is built using [clipanion][clipanion]. + +This is the next generation TypeScript based Developer Portal CLI. The goal of +this project is to make a higher quality CLI tool over the initial sync script. + + +## Install + +``` +> npm install -g kong-portal-cli +``` + +## Usage + +The easiest way to start is by cloning the [portal-templates repo][templates] +master branch locally. + +Next, edit `workspaces/default/cli.conf.yaml` to set workspace `name` and `rbac_token` +to match your setup. + +Make sure Kong is running and portal is on. + +Now, from the root folder of the templates repo, you can run: + +```portal [-h,--help] [--config PATH] [-v,--verbose] ``` + +Where `` is one of: + +* `config` Output or change configuration of the portal on the given +`workspace`, locally. +* `deploy` Deploy changes made locally under the given workspace upstream. +* `disable` Enable the portal on the given workspace. +* `enable` Enable the portal on the given workspace. +* `fetch` Fetches content and themes from the given workspace. +* `wipe` Deletes all content and themes from upstream workspace + +Where indicates the directory/workspace pairing you would like to operate on. + +#### For `deploy` +- Add `-W` or `--watch` to make changes reactive. +- Add `-P` or `--preserve` to avoid deleting files upstream that you do not have locally. +- Add `-D` or `--disable-ssl-verification` to disable SSL verification and use self-signed certs. +- Add `-I` or `--ignore-specs` to ignore the `/specs` directory. + +#### For `fetch` +- Add `-K` or `--keep-encode` to keep binary assets as base64-encoded strings locally. +- Add `-D` or `--disable-ssl-verification` to disable SSL verification and use self-signed certs. +- Add `-I` or `--ignore-specs` to ignore the `/specs` directory. + +#### For `wipe` +- Add `-D` or `--disable-ssl-verification` to disable SSL verification and use self-signed certs. +- Add `-I` or `--ignore-specs` to ignore the `/specs` directory. + +#### For `enable` and `disable` +- Add `-D` or `--disable-ssl-verification` to disable SSL verification and use self-signed certs. + + +[clipanion]: https://github.com/arcanis/clipanion +[sync-script]: https://github.com/Kong/kong-portal-templates/blob/81382f2c7887cf57bb040a6af5ca716b83cc74f3/bin/sync.js +[cli-support]: https://github.com/Kong/kong-portal-cli/issues/new +[cli-license]: https://github.com/Kong/kong-portal-cli/blob/master/LICENSE +[cli-contributors]: (https://github.com/Kong/kong-portal-cli/contributors) +[kong-support]: https://support.konghq.com/support/s/ +[templates]: https://github.com/Kong/kong-portal-templates diff --git a/app/gateway/2.7.x/developer-portal/index.md b/app/gateway/2.7.x/developer-portal/index.md new file mode 100644 index 000000000000..0b8ef0279a73 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/index.md @@ -0,0 +1,12 @@ +--- +title: Kong Dev Portal +badge: enterprise +--- + +The Kong Dev Portal provides a single source of truth for all developers +to locate, access, and consume services. With intuitive content management for +documentation, streamlined developer onboarding, and role-based access control +(RBAC), Kong’s Dev Portal provides a comprehensive solution for creating +and customizing a unified developer experience. + +![Dev Portal](/assets/images/products/gateway/dev-portal/developer-portal-homepage.png) diff --git a/app/gateway/2.7.x/developer-portal/portal-api.md b/app/gateway/2.7.x/developer-portal/portal-api.md new file mode 100644 index 000000000000..8221fc0ff083 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/portal-api.md @@ -0,0 +1,15 @@ +--- +title: Portal API +no_version: true +toc: false +layout: default +--- + + + + + + diff --git a/app/gateway/2.7.x/developer-portal/structure-and-file-types.md b/app/gateway/2.7.x/developer-portal/structure-and-file-types.md new file mode 100644 index 000000000000..8278a31718e4 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/structure-and-file-types.md @@ -0,0 +1,319 @@ +--- +title: Developer Portal Structure and File Types +badge: enterprise +--- + +The Kong Portal templates have been completely revamped to allow for easier customization, clearer separation of concerns between content and layouts, and more powerful hooks into Kong lifecycle/data. Under the hood, we have implemented a flat file CMS built on top of the `https://github.com/bungle/lua-resty-template` library. This system should feel familiar for anyone who has worked with projects like `jekyll`, `kirby cms`, or `vuepress` in the past. + +{:.note} +>Note: To follow along with this guide, it is best to clone the [kong-portal-templates repo](https://github.com/Kong/kong-portal-templates) and check out the `master` branch. This guide makes the assumption that you are working within a single workspace (the templates repo can host many different sets of portal files per workspace). Navigate to the `workspaces/default` directory from root to view the default workspaces portal files. + +## Directory Structure + +Navigate to `workspaces/default` from the `kong-portal-templates` root directory to access the default portals template files. The relative file structure in this directory directly maps to the file `path` schema attribute. (`content/homepage.txt` here maps to `content/homepage.txt` in Kong). + +From `workspaces/default`, you can see the different elements that make up a single instance of the kong developer portal: +- **content/** + - The content directory contains files that determine both site structure of the Kong Dev Portal as well as the dynamic content that renders within each page. +- **specs/** + - Specs are similar to content in that they contain the data needed to render dynamic content on the page. In the case of `specs`, the files contain valid OAS or Swagger to be rendered as a spec. +- **themes/** + - The theme directory contains different themes to be applied to the content of the portal. Each theme contains HTML templates, assets, and a config file that sets global styles available to the theme. +- **portal.conf.yaml** + - This config file determines which theme the portal uses to render, the name of the portal, as well configuration for special behavior such as redirect paths for user actions like login/logout. +- **router.conf.yaml (optional)** + - This optional config file overrides the portals default routing system with hardcoded values. This is useful for implementing single page applications, as well as for setting a static site structure. + +## Portal Configuration File + +### Path +- **format:** `portal.conf.yaml` +- **file extensions:** `.yaml` + +### Description +The Portal Configuration File determines which theme the portal uses to render, the name of the portal, as well as configuration for special behavior such as redirect paths for user actions like login/logout. It is required in the root of every portal. There can only be one Portal Configuration File, it must be named `portal.conf.yaml`, and it must be a direct child of the root directory. + +### Example + +```yaml +name: Kong Portal +theme: + name: light-theme +redirect: + unauthenticated: login + unauthorized: unauthorized + login: dashboard + logout: '' + pending_approval: '' + pending_email_verification: '' +collections: + posts: + output: true + route: /:stub/:collection/:name + layout: post.html +``` + +- `name`: + - **required**: true + - **type**: `string` + - **description**: The name attribute is used for meta information, such as setting a title for your portal in the browser tab. + - **example**: `Kong Portal` +- `theme` + - **required**: true + - **type**: `object` + - **description**: The theme object is used for declaring which theme you would like your portal to render, as well as theme style overrides. While the overrides are not required, declaring which theme you would like to use is. +- `redirect` + - **required**: true + - **type**: `object` + - **description**: The redirect object informs kong how to redirect the user after certain actions. If one of these values is not set, Kong serves a default template based off of the action. Each key represents the name of the action taking place, the value represents the route to which the application redirects the user. +- `collections` + - **required**: false + - **type**: `object` + - **description**: Collections are a powerful tool enabling you to render sets of content as a group. Content rendered as a collection share a configurable route pattern, as well as a layout. For more information check out the [collections](/gateway/{{page.release}}/developer-portal/working-with-templates/#collections) section of our [Working with Templates](/gateway/{{page.release}}/developer-portal/working-with-templates/) guide. + + +## Router Configuration File (Optional) + +### Path +- **format:** `router.conf.yaml` +- **file extensions:** `.yaml` + +### Description +This optional config file overrides the portals default routing system with hardcoded values. This is useful for implementing single page applications, as well as for setting a static site structure. There can only be one Router Configuration File, it must be named `router.conf.yaml`, and it must be a direct child of the root directory. + +### Example +The `router.conf.yaml` file expects sets of key-value pairs. The key should be the route you want to set; the value should be the content file path you want that route to resolve to. Routes should begin with a backslash. `/*` is a reserved route and acts as a catchall/wildcard. If the requested route is not explicitly defined in the config file, the portal will resolve to the wildcard route if present. + +```yaml +/*: content/index.txt +/about: content/about/index.txt +/dashboard: content/dashboard.txt +``` + +## Content Files + +### Path +- **format:** `content/**/*` +- **file extensions:** `.txt`, `.md`, `.html`, `.yaml`, `.json` + +### Description +Content files establish portal site structure, as well as provide its accompanying HTML layout with metadata and dynamic content at the time of render. Content files can be nested in as many subdirectories as desired as long as the parent directory is `content/`. + +In addition to providing metainfo and content for the current page at time of render, content files determine the path at which a piece of content can be accessed in the browser. + +| Content Path | Portal URL | +|-------------|---------------------------| +| `content/index.txt` | `http://portal_gui_url/` | +| `content/about.txt` | `http://portal_gui_url/about` | +| `content/documentation/index.txt` | `http://portal_gui_url/documentation` | +| `content/documentation/spec_one.txt` | `http://portal_gui_url/documentation/spec_one` | + +### Contents +``` +--- +title: homepage +layout: homepage.html +readable_by: [red, blue] +--- + +Welcome to the homepage! +``` + +File contents can be broken down into two parts: `headmatter` and `body`. + +### headmatter + +The first thing to notice in the example files contents are the two sets of `---` delimiters at the start. The text contained within these markers is called `headmatter` and always gets parsed and validated as valid `yaml`. `headmatter` contains information necessary for a file to render successfully, as well as any information you would like to access within a template. Kong parses any valid `yaml` key-value pair and becomes available within the content's corresponding HTML template. There are a few reserved attributes that have special meaning to Kong at the time of render: + +- `title`: + - **required**: false + - **type**: `string` + - **description**: The title attribute is not necessary but is recommended. When set, this will set the title of a page in the browser tab. + - **example**: `homepage` +- `layout` + - **required**: true + - **type**: `string` + - **description**: The layout attribute is required for each piece of content, and determines what HTML layout to use in order to render the page. This attribute assumes a root of the current themes layout directory (`themes//layouts`). + - **example**: `bio.html` or `team/about.html` +- `readable_by` + - **required**: false + - **type**: `array` (multiple), `string` (singular) + - **description**: The optional `readable_by` attribute determines which developers can access a piece of content. In the case of the example above, only developers with rbac roles of "red" or "blue" may access the `/homepage` route. + - **example**: `[red, blue]` (multiple), `red` (singular) + +- `route` + - **required**: false + - **type**: `string` + - **description**: This optional attribute overrides the generated route Kong assigns to content, and replaces it with the route included here. + - **example**: `route: /example/dog` renders the example page above at `/example/dog` instead of the autogenerated `/homepage` route. +- `output` + - **required**: false + - **type**: `boolean` + - **default**: `true` + - **description**: This optional attribute is `true` by default and determines whether a piece of content should be rendered. No route or page gets created when this value is set to `false`. +- `stub` + - **required**: false + - **type**: `string` + - **description**: Used by `collection` config to determine custom routing. You can read more about Collections in the collections section of the _working with templates_ guide. + +#### body +The information located under headmatter represents the content body. Body content is freeform and gets parsed as by the file extension included in the file path. In the case of the example above, the file is `.txt` and is available in the template as such. + +## Spec Files + +### Path +- **format:** `specs/**/*` +- **file extensions:** `.yaml`, `.json` + +### Description +Specs are similar to `content` files in that they provide the dynamic data needed to render a page, as well as any metadata a user wants to provide as `headmatter`. The format in which these are provided to the Portal differs from `content` files, which can be seen in the example below. + +>It is recommended to keep spec folder structure flat. Spec files must be valid OAS or Swagger `.yaml`/`.yml` or `.json` files. + +### Contents + +``` +swagger: "2.0" +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +host: petstore.swagger.io +basePath: /v1 +x-headmatter + - key1: val1 + - key2: val2 +... +``` + +Spec file contents themselves should be valid OAS or Swagger specifications. If you want +to inject headmatter into the specification, you can do so by including an `x-headmatter` +key to the root of the spec object. This may be useful if you wanted to, for example, +provide your own renderer template via `x-headmatter.layout` or override the spec's default +route via `x-headmatter.route`. + +Example: +``` +swagger: "2.0" +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +host: petstore.swagger.io +basePath: /v1 +x-headmatter: + layout: custom/my-spec-renderer.html <- Custom Layout + route: my-special-route/myfirstspec <- Custom Route +... +``` + +Specs are a collection, meaning their `layout` and `route` are determined by the +portal configuration and not the file itself. Specs are rendered by default with +the `system/spec-renderer.html` layout, under the route pattern `/documentation/:name`, +where `:name` is the name of the particular spec file. So a spec with a path of +`specs/myfirstspec.json` renders in the portal as `/documentation/myfirstspec`. +If you want to overwrite the hardcoded spec collection config, you can do so by +including your own in `portal.conf.yaml`. Check out the Collections section of +our `Working with Templates` guide to learn more. + +You can also use the [Portal Files API](/dev-portal/api/v1/) +to `POST`, `GET`, `PATCH`, and `DELETE` content, spec, and theme files. + +## Theme Files +### Themes Directory Structure +The theme directory contains different instances of portal themes, each one of which determines the look and feel of the developer portal via HTML/CSS/JS. Which theme is used at time of render is determined by setting `theme.name` within `portal.conf.yaml`. Setting `theme.name` to `best-theme` causes the portal to load theme files under `themes/best-theme/**`. + +Each theme file is composed of a few different folders: +- **assets/** + - The assets directory contains static assets that layouts/partials will reference at time of render. Includes CSS, JS, font, and image files. +- **layouts/** + - The layouts directory contains HTML page templates that `content` reference via the `layout` attribute in headmatter (see `content` section). +- **partials/** + - The partials directory contains HTML partials to be referenced by layouts. Can be compared to how layouts and partials interacted in the legacy portal. +- **theme.conf.yaml** + - This config file sets color and font defaults available to templates for reference as CSS variables. It also determines what options are available in the Kong Manager Appearance page. + +### Theme Assets + +#### Path +- **format:** `theme/*/assets/**/*` + +#### Description +The asset folder contains CSS/JS/fonts/images for your templates to reference. + +To access asset files from your templates, keep in mind that Kong assumes a path from the root of your selected theme. + +| Asset Path | Href Element | +|--------------------------|---------------------------| +| `themes/light-theme/assets/images/image1.jpeg` | `` | +| `themes/light-theme/assets/js/my-script.js` | `` | +| `themes/light-theme/assets/styles/my-styles.css` | `` | + +>Note: Image files uploaded to the `theme/*/assets/` directory should either be a svg text string or `base64` encoded, `base64` images will be decoded when served. + +### Theme Layouts + +#### Path +- **format:** `theme/*/layouts/**/*` +- **file extensions:** `.html` + +#### Description +Layouts act as the HTML skeleton of the page you want to render. Each file within the layouts directory must have an `html` filetype. They can exist as vanilla `html`, or can reference partials and parent layouts via the portals templating syntax. Layouts also have access to the `headmatter` and `body` attributes set in `content`. + +The example below shows what a typical layout could look like. + +{% raw %} +```html +
    + {(partials/header.html)} <- syntax for calling a partial within a template +
    +
    +

    {{page.title}}

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

    {{page.body}}

    <- 'body' retrieved from page body +
    +
    + {(partials/footer.html)} +
    +``` +{% endraw %} + +To learn more about the templating syntax used in this example, check out our [templating guide](/gateway/{{page.release}}/developer-portal/working-with-templates/). + +### Theme Partials + +#### Path +- **format:** `theme/*/partials/**/*` +- **file extensions:** `.html` + +#### Description +Partials are very similar to layouts: they share the same syntax, can call other partials within themselves, and have access to the same data/helpers at time of render. The thing that differentiates partials from layouts it that layouts call on partials to build the page, but partials cannot call on layouts. + +The example below shows the `header.html` partial referenced from the example above: + +{% raw %} +```html +
    +
    +
    + <- can access the same page data the parent layout +
    +
    + {(partials/header_nav.html)} <- partials can call other partials +
    +
    +
    +``` +{% endraw %} + +### Theme Configuration File + +#### Path +- **format:** `theme/*/theme.conf.yaml` +- **file extensions:** `.yaml` + +#### Description +The Theme Configuration File determines color/font/image values a theme makes available for templates/CSS at the time of render. It is required in the root of every theme. There can only be one Theme Configuration File, it must be named `theme.conf.yaml`, and it must be a direct child of the themes root directory. diff --git a/app/gateway/2.7.x/developer-portal/theme-customization/adding-javascript-assets.md b/app/gateway/2.7.x/developer-portal/theme-customization/adding-javascript-assets.md new file mode 100644 index 000000000000..5caa4047d162 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/theme-customization/adding-javascript-assets.md @@ -0,0 +1,55 @@ +--- +title: Adding and Using JavaScript Assets in Kong Dev Portal +badge: enterprise +--- + +The Kong Developer Portal ships with Vue, React, and jQuery already loaded. +You may want to make use of these libraries to write custom interactive +webpages or load additional JavaScript. + +> Note: This guide is for adding/using JavaScript assets without changing server-side routing. [Learn more about a SPA to the Dev Portal](/gateway/{{page.release}}/developer-portal/theme-customization/single-page-app/). + +## Prerequisites + +* Portal Legacy is turned off +* The Kong Developer Portal is enabled and running +* The [kong-portal-cli tool](/gateway/{{page.release}}/developer-portal/helpers/cli/) is installed locally + + +## Adding JS Assets +> Warning: Due to compatibility issues, avoid using any React version other than React 15 on the `layouts/system/spec-render.html` layout. We recommend using the version of React included by the default base theme. + +To add JavaScript assets: +1. Clone the [kong-portal-templates](https://github.com/Kong/kong-portal-templates) repo. +2. Add any JavaScript files to the `themes/base/js` folder. +3. Deploy using the [kong-portal-cli-tool](/gateway/{{page.release}}/developer-portal/helpers/cli/). + + +## Loading JS Assets + +You can make use of the existing Vue and jQuery in any layout/partial that includes `partials/theme/required-scripts.html` where these scripts are loaded. + +By default, React is only loaded on `layouts/system/spec-render.html`. + +If you want to load React or any custom JavaScript asset on all pages, you can edit `themes/partial/foot.html`. + + +{% raw %} +``` +{% layout = "layouts/_base.html" %} + +{-main-} + {(partials/header.html)} + +
    + {* blocks.content *} +
    + + {(partials/footer.html)} + + +{-main-} +``` +{% endraw %} + +Alternatively, you can load the script you need on the specific layout for each content page as needed. diff --git a/app/gateway/2.7.x/developer-portal/theme-customization/alternate-openapi-renderer.md b/app/gateway/2.7.x/developer-portal/theme-customization/alternate-openapi-renderer.md new file mode 100644 index 000000000000..504ad59bfaa5 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/theme-customization/alternate-openapi-renderer.md @@ -0,0 +1,22 @@ +--- +title: Alternate OpenAPI Renderer +badge: enterprise +--- + +Through Kong Manager, use the Dev Portal [Editor](/gateway/{{page.release}}/developer-portal/using-the-editor/) to customize how your API specs render in your Dev Portal. + +To do this, add some custom code and update your config, as follows: + +1. In Kong Manager, navigate to the Dev Portal Editor from the left sidebar. + +1. Navigate to **Themes** > **base** > **layout** > **system** > **`spec.renderer.html`**. + +1. In `spec.renderer.html`, replace all of the current content with the content from this [spec-renderer.html](https://github.com/Kong/docs.konghq.com/blob/{{ site.git_branch }}/app/code-snippets/_spec-renderer.html) file. Doing so adds options for [Stoplight](https://meta.stoplight.io/docs/platform/ZG9jOjIwNjk2MQ-welcome-to-the-stoplight-docs) and [Redoc](https://github.com/Redocly/redoc) layouts. + +1. In `theme.conf.yaml`, add the parameter `spec_render_type` and the value `stoplight` or `redoc`. For example: + + ```yaml + spec_render_type: "stoplight" + ``` + +1. Refresh your Dev Portal to see that the change has taken effect. diff --git a/app/gateway/2.7.x/developer-portal/theme-customization/easy-theme-editing.md b/app/gateway/2.7.x/developer-portal/theme-customization/easy-theme-editing.md new file mode 100644 index 000000000000..008681c36445 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/theme-customization/easy-theme-editing.md @@ -0,0 +1,29 @@ +--- +title: Easy Theme Editing in Kong Manager +badge: enterprise +--- + +The Kong Developer Portal ships with a default theme, including preset images, background colors, fonts, and button styles. These settings can be edited quickly and easily from within Kong Manager, without the need to edit code. + +## Prerequisites + +* Access to Kong Manager +* The Developer Portal is enabled and running + +## The Appearance Tab + +{:.note} +> **Note**: Styling does not automatically carry over from the default Dev Portal to different Dev Portals in other workspaces. See [Migrating Templates Between Workspaces](/gateway/{{page.release}}/developer-portal/theme-customization/migrating-templates/) to learn how to manually copy templates to workspaces where you want to duplicate the styling. + +From the **Workspace** dashboard in **Kong Manager**, click on the **Appearance** tab under **Dev Portal** on the left side bar. +This will open the Developer Portals theme editor. From this page, the header logo, background colors, font colors, and button styles can be edited using the color picker interface. + +The predefined variables refer to the following elements: + +![Appearance Tab - Variables](/assets/images/products/gateway/dev-portal/appearance-dev-portal.png) + +Hovering over an element will show a color picker, as well as a list of predefined colors. These colors are defined by the current template and can be edited in the [theme.conf.yaml](#editing-theme-files-with-the-editor) file + +## Editing Theme Files with the Editor + +The Dev Portal Editor within Kong Manager exposes the default Dev Portal theme files. The theme files can be found at the bottom of the file list under *Themes*. The variables exposed in the *Appearance* tab can be edited in the `theme.conf.yaml` file. See [Using the Editor](/gateway/{{page.release}}/developer-portal/using-the-editor/) for more information on how to edit, preview, and save files in the Editor. diff --git a/app/gateway/2.7.x/developer-portal/theme-customization/emails.md b/app/gateway/2.7.x/developer-portal/theme-customization/emails.md new file mode 100644 index 000000000000..44f9dd65e2fa --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/theme-customization/emails.md @@ -0,0 +1,204 @@ +--- +title: Customizing Portal Emails +badge: enterprise +--- + +You can manage the message and appearance of emails being sent by the Kong Developer Portal. +Editable email templates are loaded as files similar to content files for portal rendering. +Email files can be managed in the same way as other files for rendering, via editor or via the Portal CLI Tool. +This feature is **not** supported on legacy portal mode. + +If no email templates are loaded, Kong will fall back to the same emails as {{site.base_gateway}} 1.3.0.0. +Enabling a non-legacy portal on new workspaces loads default editable email templates. +For existing non-legacy Portals, editable email templates must be loaded manually. + +Email-specific values are templated in tokens that work similarly to templating in portal layouts and partials. +Not all tokens are supported on all emails. + +## Prerequisites + +* The Kong Developer Portal is not running in **Legacy Mode** +* The Kong Developer Portal is enabled and running +* [The emails you want are enabled in kong](/gateway/{{page.release}}/developer-portal/configuration/smtp/#portal_invite_email) +* If using CLI tool, kong-portal-cli tool 1.1 or later is installed locally and git installed + +## Understanding Email Files + +Portal templates use a combination of HTML, markdown, and [`tokens`](#token-descriptions). + +The follow example is the `emails/approved-access.txt` template: + + +{% raw %} +```yaml +--- +layout: emails/email_base.html + +subject: Developer Portal access approved {{portal.url}} +heading: Hello {{email.developer_name}}! +--- +You have been approved to access {{portal.url}}. +
    +Please visit {{portal.url}}/login to login. +``` +{% endraw %} + +Like other content files, these files have a headmatter between the two `---` . The layout is set by `layout` attribute, this is the layout file this email will render with. + +- `subject` sets the subject line for email. +- `heading` is an optional value that by default is rendered as a h3 + +The body of the email is HTML content. You can reference the tokens allowed for the email in the table below. In this case, {% raw %}`{{portal.url}}`{% endraw %} is used to access the portal url + +## Supported Emails and Tokens + +{% raw %} +|Path |Supported Tokens |Required Tokens |Description| +|--- |--- |--- |--- | +|`emails/invite.txt` | `{{portal.gui_url}}` `{{email.developer_email}}` | `{{portal.gui_url}}` |email sent to developer who is invited to a portal from the manager | +|--- |--- |--- |--- | +|`emails/request-access.txt` |`{{portal.gui_url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` `{{email.admin_url}}` |`{{portal.gui_url}}` `{{email.developer_email}}` |email sent to admin when a developer signs up for portal, in order to approve the developer | +|`emails/approved-access.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` |`{{portal.gui_url}}` |email sent to developer when their account is approved | +|`emails/password-reset.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` `{{email.token}}` `{{email.token_exp}}` `{{email.reset_url}}` |`{{portal.url}}` `{{email.token}}` or `{{email.reset_url}}` |email sent to developer when a password reset is requested (basic-auth only) | +|`emails/password-reset-success.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` |`{{portal.url}}` |email sent to developer when a password reset is successful (basic-auth only) | +|emails/account-verification.txt |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` `{{email.token}}` `{{email.verify_url}}` `{{email.invalidate_url}}` |`{{portal.url}}` `{{email.token}}` or both `{{email.verify_url}}` and `{{email.invalidate_url}} ` |email sent to developer when `portal_email_verification` is on to verify developer email (basic-auth only) | +|`emails/account-verification-approved.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` |`{{portal.url}}` |email sent to developer when `portal_email_verification` is on and developer has verified email and developer has been approved by admin/auto-approve is on (basic-auth only) | +|`emails/account-verification-pending.txt` |`{{portal.url}}` `{{email.developer_email}}` `{{email.developer_name}}` `{{email.developer_meta.*}}` |`{{portal.url}}` |email sent to developer when `portal_email_verification` is on and developer has verified email and developer has yet to be approved by admin (basic-auth only) | +{% endraw %} + +## Token Descriptions + +{% raw %} +|Token |Description | +|--- |--- | +|`{{portal.url}}` |Dev Portal URL for the workspace | +|--- |--- | +|`{{email.developer_email}}` |Developer's email | +|`{{email.developer_name}}` |Developer's full name, this value is collected as part of registration by default. If meta-fields are edited to not include full_name then this will fallback to email | +|`{{email.developer_meta.*}}` |Developer's meta-fields, these value are collected as part of registration. They must be configured prior to registration. If the value doesn't exist or is optional and blank, it will display as an empty string. If the `developer_meta` configuration doesn't specify the field, it will appear as-is without replacement, e.g. `{{email.developer_meta.preferred_name}}`| +|`{{email.admin_url}}` |Kong Manager URL | +|`{{email.reset_url}}` |Dev Portal full URL for resetting password (assumes default path for password reset) | +|`{{email.token_exp}}` |Human readable string for amount of time from sending of email, password reset token/url is valid. | +|`{{email.verify_url}}` |Link to verify account (assumes default path for account verification)) | +|`{{email.invalidate_url}}` |Link to invalidate account verification request (assumes default path for account verification)) | +|`{{email.token}}` |Can be used in combination with `{{portal.url}}` to manually build url string for password reset and account verification/invalidation. **Not recommended for use**, unless custom path for password reset or account verification has been set. | +{% endraw %} + +## Editing Email Templates + +The default email templates will be automatically loaded into the Kong Developer Portal's file system when the Dev Portal is activated. These templates can now be edited in Kong Manager via the **Portal Editor** or via the **Portal CLI** tool. + +### Editing via the Portal Editor + +Email templates can now be edited in the Portal Editor along with the rest of the files in the Kong Developer Portal file system. To view and edit these files: + +1. Log into Kong Manager and navigate to the Workspace whose Dev Portal you wish to edit. +2. Select the **Editor** from the sidebar under **Dev Portal**. + +The email templates can be found under the **Emails** section in the Portal Editor sidebar. + +### Editing via the Portal CLI Tool + +1. Clone [https://github.com/Kong/kong-portal-templates] master branch, and navigate into its directory. +2. If you have any customizations or permissions changes that you want to keep: + Run `portal fetch ` This will pull in your modifications locally. +3. After making any changes, `portal deploy ` to deploy all files. + +## Editing Email Appearance + +To edit the appearance of emails, you can change the layout file emails use. +By default, emails are set to use the layout `emails/email_base.html`. If this file does not exist inside your theme (default theme is `base`), then a hardcoded fallback will be used. + +You can edit the layout this layout file via the Portal Editor or locally with the Portal CLI tool. Follow the instructions for the editing email text, but modifying the layout file instead. + +If you want different emails to have a different appearance, you can set different layout files for each email file. + +The default email layout looks like: + +{% raw %} +```html + + + + + + {{portal.name}} +

    {{page.heading}}

    +

    + {*page.body*} +

    + + +``` +{% endraw %} + +The `img` tag loads the logo that can be set in the appearance tab in the manager. If you do not want to display a logo, remove the `` tag. If you want to set different sizing for your logo, you can change the inline style attribute. + +{:.note} +> The logo will not render for many email clients that pre-fetch images if portal is not set to be accessible from a public url (for example if you are testing the Portal with a localhost). + +By modifying the HTML of this file, you can change the appearance of your emails. For example if you wanted to add a footer that would show on all emails, add it under the `

    ` tag + +Be sure to keep in mind the HTML support limitations of the email clients you plan to support. + +## Loading Email Templates on Existing Dev Portals + +Editable email templates can be loaded either via the editor or via the `kong-portal-cli` tool. + +### Load Email Templates via the Portal Editor + +1. Log into Kong Manager and navigate to the workspace you want to edit. Click on **Editor** in the sidebar. +2. Click **New File+**. +3. Select Content type `email`. +4. Type in one of the supported paths from above. +5. Click **Create File** to generate a default email template that is valid for that email. +6. Do this for emails you want to edit. + + Note: By default, these emails you create will have layout key set: `layout: emails/email_base.html`. + If you don’t create this layout file, all emails fallback to a default layout. + You will want to create this layout if you want to customize the Appearance of emails in addition to message. + +To create an email layout: + +1. Click **New File+**. +2. Select Content type `theme`. +3. Type in the path for the layout, `themes//layouts/email_base.html`. The default theme name is base. + The layout that loads in the new portals in 1.3.0.1 is the following (this adds the logo image that can be set in the appearance tab in the manager): + +{% raw %} +```html + + + + + + {{portal.name}} +

    {{page.heading}}

    +

    + {*page.body*} +

    + + +``` +{% endraw %} + +Find out more about customizing the email layout in the section below. + +### Load Email Templates via the Portal CLI Tool + +1. Clone the [portal templates master branch](https://github.com/Kong/kong-portal-templates) and + navigate into the folder you cloned. +2. If you have any customizations or permissions changes that you want to keep: + + 1. Run `portal fetch `. This pulls in your modifications locally. + + 2. Merge in the portal templates master branch + to apply changes for 1.3.0.1, including emails. + +3. Run `portal deploy `. This deploys all files. diff --git a/app/gateway/2.7.x/developer-portal/theme-customization/markdown-extended.md b/app/gateway/2.7.x/developer-portal/theme-customization/markdown-extended.md new file mode 100644 index 000000000000..c987763e9a93 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/theme-customization/markdown-extended.md @@ -0,0 +1,43 @@ +--- +title: Markdown Rendering Module +badge: enterprise +--- + +The Kong Developer Portal supports +[Github-flavored markdown](https://github.github.com/gfm/) (GFM) that can be +used in lieu of the [templates](/gateway/{{page.release}}/developer-portal/working-with-templates/). Instead of having to +create an HTML layout and partials for your templates, you can use custom CSS +with the improved markdown rendering module. The extended markdown support +improves rendering significantly, especially for tables. + +## Prerequisites + +* Access to Kong Manager +* The Developer Portal is enabled and running + +## Specify the markdown rendering module in a document + +1. Create a markdown file for your Dev Portal documentation. +2. Call the markdown module using the `layout` parameter. +3. Specify the `.css` file you want to use. You can use the default Github `.css` as shown, or specify your own custom `.css`. + + - All markdown CSS classes should be prepended by `.markdown-body`. This is + to ensure that markdown styles do not bleed into other areas of the portal. + - The `.css` file should be placed in the current theme's `/assets` directory. + - The renderer assumes the `.css` path will begin from the `/assets` + directory. See the example below. + - Other classes defined in any other Dev Portal CSS external to the + `markdown.css` may pollute your rendered markdown. If you want to unset + particular styles, you can do so using the + `/assets/style/markdown-fixes.css` file. + +### Example + +`/content/markdown-example.md` + +``` +--- +layout: system/markdown.html +css: assets/style/markdown.css +--- +``` diff --git a/app/gateway/2.7.x/developer-portal/theme-customization/migrating-templates.md b/app/gateway/2.7.x/developer-portal/theme-customization/migrating-templates.md new file mode 100644 index 000000000000..f5052136f565 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/theme-customization/migrating-templates.md @@ -0,0 +1,46 @@ +--- +title: Migrating Templates Between Workspaces +badge: enterprise +--- + +The template styling from your default Dev Portal doesn't automatically apply to new Dev Portals you create in other workspaces. However, with the [Portal CLI](/gateway/latest/developer-portal/helpers/cli/), you can move over templates in a few steps. + +## Prerequisites + +* Install [Portal CLI](/gateway/latest/developer-portal/helpers/cli/) and set up the [configuration](/gateway/latest/developer-portal/helpers/cli/#usage). + +## Apply customization from default Dev Portal + +To apply customizations from one Dev Portal to another, do the following: + +1. From your Kong Manager, create a new Workspace and enable a new Dev Portal. In the rest of this document, the new Workspace name will be referred to as `{WORKSPACE_NAME}`. + +1. Clone the Kong Portal Templates repository: + + ```bash + git clone https://github.com/Kong/kong-portal-templates + ``` + +1. Move into `kong-portal-templates`: + + ```bash + cd kong-portal-templates + ``` + +1. Fetch the default workspace: + + ```bash + portal fetch default + ``` + +1. Copy the templates from the default workspace to another workspace: + + ```bash + cp workspaces/default workspaces/{WORKSPACE_NAME} + ``` + +1. Deploy the templates to the new workspace: + + ```bash + portal deploy {WORKSPACE_NAME} + ``` diff --git a/app/gateway/2.7.x/developer-portal/theme-customization/single-page-app.md b/app/gateway/2.7.x/developer-portal/theme-customization/single-page-app.md new file mode 100644 index 000000000000..f17fbf4cd684 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/theme-customization/single-page-app.md @@ -0,0 +1,144 @@ +--- +title: Hosting Single Page App out of Kong Dev Portal +badge: enterprise +--- + +The Kong Developer Portal ships with a default server-side rendered theme; however, it is possible to replace this with a Single Page App (SPA). This example is in Angular using the Angular CLI Tool, but you can follow along with any other JavaScript framework with just a few tweaks. + +To view the basic example Angular template from this guide, visit the [`example/spa-angular`](https://github.com/Kong/kong-portal-templates/tree/example/spa-angular) branch from the `kong-portal-templates branch`. + +## Prerequisites + +* Portal Legacy is turned off +* The Developer Portal is enabled and running +* kong-portal-cli tool is installed locally + +## What is a SPA + +A Single Page App (SPA) is a website that loads all HTML, JavaScript, and CSS on the first load. Instead of loading subsequent pages from the server, JavaScript is used to dynamically change the page content. You may want to use an SPA in Dev Portal if you have a preexisting SPA you want to integrate with the portal, or you are trying to achieve a more application-like experience across many pages. An SPA takes control of routing from the server, and handles it client-side instead. + +Custom JavaScript can also be added to run only on specific layouts, allowing you to maintain server-side rendering. [Learn more](/gateway/{{page.release}}/developer-portal/theme-customization/adding-javascript-assets/) about adding JavaScript to a layout without implementing an SPA. + +## Making Choices + + +We recommend Catalog and Spec routes not be handled by SPA. +If you are using Authentication, then you probably also want to leave server-side rendering for any account pages. + +## Getting Started + +Clone the [portal-templates](https://github.com/Kong/kong-portal-templates) repo + +Create a file called `router.conf.yaml` in `workspaces/default` This file will override the default routing, allowing you to control routing via JavaScript. + +`router.conf.yaml` must be a yaml file, where the key is each route, and the value a content or spec path. `/*` Is a catch-all wildcard for all routes not specified in `router.conf.yaml`, it will overwrite all default routing set by collections or set in headmatter. + +In the `router.conf.yaml` example below, we are hardcoding routing for all kong related functionality and deferring to SPA routing for all other routes. The `/*` route at the bottom of the file is a wildcard route. The wildcard route, in this case, tells Kong to serve `content/index.txt` for any request that is not handled by the route declarations above. + +``` +/login: content/login.txt +/logout: content/logout.txt +/register: content/register.txt +/settings: content/settings.txt +/reset-password: content/reset-password.txt +/account/invalidate-verification: content/account/invalidate-verification.txt +/account/resend-verification: content/account/resend-verification.txt +/account/verify: content/account/resend-verification.txt +/documentation: content/documentation/index.txt +/documentation/httpbin: specs/httpbin.json +/documentation/petstore: specs/petstore.yaml +/*: content/index.txt + +``` + +### Create your SPA + +Create an SPA app in the JavaScript framework of your choice. This +example uses angular. + +``` +ng new +``` + +Make sure to include a 404 route, as well as all routes you want to have on the Portal (excluding the routes handled by server-side rendering excluded above). + +Run the build process + +For angular: + +``` +ng build +``` + +Copy the build output JS and CSS files to a folder inside `workspaces/default/themes/assets/js`. + +For this example, place the angular build inside a `workspaces/default/themes/assets/js/ng`. + +### Mounting an SPA + +To load our JS, we need to mount it. Let's create a new layout page. + +Create a file called `spa.html` in `workspaces/default/themes/layouts`. + +This file will need to contain the HTML element that the SPA will mount to as well as the scripts necessary to do this. +For reference, view the `index.html` inside the build folder created by the build step of the SPA. + +The example uses `layouts/_base.html` as the base for the layout template. +By doing so, the element is handled the same way as other pages in the portal, as well as the same CSS and scripts. + +If you want to have the top nav bar and bottom nav bar, be sure to include them in your layout. + +This is the resulting layout: + +{% raw %} +``` +{% layout = "layouts/_base.html" %} +{-main-} + + {(partials/header.html)} +
    + +
    + {(partials/footer.html)} + + + + + + + + + + + + + +{-main-} +``` +{% endraw %} + +If the SPA build process creates a CSS file, edit the `head.html` partial to include your CSS file. + +### Loading your layout + +Modify `workspaces/default/content/index.txt` to use your layout. +The title you set here will be the one that displays until the JS set title loads. + +{% raw %} +``` +--- +layout: spa.html +title: Home +--- +``` +{% endraw %} + +### Deploy the Portal + +Now using the kong-portal-cli tool, deploy the portal. + +From the root folder of the templates repo: + +``` +portal deploy default +``` diff --git a/app/gateway/2.7.x/developer-portal/using-the-editor.md b/app/gateway/2.7.x/developer-portal/using-the-editor.md new file mode 100644 index 000000000000..c553a2a764d0 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/using-the-editor.md @@ -0,0 +1,51 @@ +--- +title: Using the Editor through Kong Manager +badge: enterprise +--- + +Kong Manager offers a robust file editor for editing the template files of the Dev Portal from within the browser. + +## Prerequisites + +* Access to Kong Manager +* The Kong Developer Portal is **enabled** and **running** + +>NOTE: Editor Mode is *not* available when running the Dev Portal in **legacy** mode. + +## Enter Editor Mode + +From the **Kong Manager** dashboard of your **Workspace**, click **Editor** under **Dev Portal** in the sidebar. + +This will launch the **Editor Mode**. +## Navigating the Editor + +When enabled, the Dev Portal is pre-populated with Kong's default theme. The file editor exposes these files to the UI, allowing them to be edited quickly and easily from inside the browser. When you first open the editor, you will be presented with a list of files on the left, and a blank editing form. + +1. Create new files for the Dev Portal right from the Editor by clicking `New File+`. +1. List of all exposed template files in the Dev Portal, separated by Content / Spec / Themes. +1. Code View - Select a file from the sidebar to show the code here. +1. Portal Preview - View a live preview of the selected Dev Portal file. +1. Toggle View - Choose between three different views: full screen code, split view, and full screen preview mode. + +![Dev Portal with Numbers](/assets/images/products/gateway/dev-portal/editor-mode-numbered.png) + +## Editing Files + +Select a file from the sidebar to open it for editing. This will expose the file to the Code View and show a live update in the Portal Preview. Clicking Save in the top right corner will save the updates to the database and update the file on the Dev Portal. + +## Adding new files + +Clicking the `New File +` button opens the New File Dialog. + +Once created, files will immediately be available from within the Editor. + +## Authenticating files + +Authentication is handled by `readable_by` value on content pages (for gui view, go to permissions page) + - set `readable_by`: '*' to equal old authenticated + - to restrict access to certain roles, set `readable_by` to an array of accepted roles (you must first create roles on the permissions page) + - for specs, `readable_by` is set inside the `x-headmatter` object + +## Deleting files + +To _permanently_ delete a file from within the Editor, right click on the filename and select **Delete** from the popup menu. diff --git a/app/gateway/2.7.x/developer-portal/working-with-templates.md b/app/gateway/2.7.x/developer-portal/working-with-templates.md new file mode 100644 index 000000000000..35df83f502a0 --- /dev/null +++ b/app/gateway/2.7.x/developer-portal/working-with-templates.md @@ -0,0 +1,1416 @@ +--- +title: Working with Templates +badge: enterprise +--- + +Kong Portal is built on top of the `lua-resty-template` templating library, which can be viewed here: [https://github.com/bungle/lua-resty-template](https://github.com/bungle/lua-resty-template). Basic usage of the library will be described below. Refer to the source documentation for a more in-depth look at what it can accomplish. + +## Syntax +***(excerpt from lua-resty-templates documentation)*** + +You may use the following tags in templates: +{% raw %} +* `{{expression}}`, writes result of expression - HTML escaped +* `{*expression*}`, writes result of expression +* `{% lua code %}`, executes Lua code +* `{(path-to-partial)}`, include `partial` file by path, you may also supply context for the file `{(partials/header.html, { message = "Hello, World" } )}` + +* `{-block-}...{-block-}`, wraps inside of a `{-block-}` to a value stored in a `blocks` table with a key `block` (in this case), see [using blocks](https://github.com/bungle/lua-resty-template#using-blocks). Don't use predefined block names `verbatim` and `raw`. +* `{-verbatim-}...{-verbatim-}` and `{-raw-}...{-raw-}` are predefined blocks whose inside is not processed by the `lua-resty-template` but the content is outputted as is. +* `{# comments #}` everything between `{#` and `#}` is considered to be commented out (i.e., not outputted or executed). +{% endraw %} + +## Show custom properties + +You may work with custom properties in your OpenAPI spec. To expose custom properties in Dev Portal, change the property `showExtensions` to `true` in the `spec-renderer.html` file. By default, `showExtensions` is `false`. + +## Partials + +Partials are snippets of HTML that layouts can reference. Partials have access to all the same data that its layout does, and can even call other partials. Breaking your code into partials can help organize large pages, as well as allow different layouts share common page elements. + +### content/index.txt + +{% raw %} +``` +--- +layout: index.html +title: Partials +header_logo: assets/images/example.jpeg +header_nav_items: + about: + href: /about + guides: + href: /guides +hero_title: Partials Info +hero_description: Partials are wicked sick! +--- +``` +{% endraw %} + +### layouts/index.html + +{% raw %} +```html +{(partials/header.html)} +
    + {(partials/hero.html)} +
    +{(partials/footer.html)} +``` +{% endraw %} + +### partials/header.html + +{% raw %} +```html +
    +
    + +
    +
    + {(partials/header_nav.html)} +
    +
    +``` +{% endraw %} + +### partials/header_nav.html + +{% raw %} +``` html +
      + {% for title, href in each(page.header_nav_items) do %} +
    • {{title}}
    • + {% end %} +
    +``` +{% endraw %} + +### partials/hero.html + +{% raw %} +``` html +

    {{page.hero_title}}

    +

    {{page.hero_description}}

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

    footer

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

    Partials Info

    +

    Partials are wicked sick!

    +
    +

    footer

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

    {{page.title}}

    +

    {{page.description}}

    +

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

    header

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

    footer

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

    header

    +
    +
    +

    Blocks

    +

    Blocks are the future!

    +

    +
    +

    footer

    +
    + + +``` +{% endraw %} + +## Collections +Collections are a powerful tool enabling you to render sets of content as a group. Content rendered as a collection share a configurable route pattern, as well as a layout. Collections are configured in your portals `portal.conf.yaml` file. + +The example below shows all the necessary configuration/files needed to render a basic `blog` collection made up of individual `posts`. + +#### portal.conf.yaml + +{% raw %} +``` +name: Kong Portal +theme: + name: base +collections: + posts: + output: true + route: /:stub/:collection/:name + layout: post.html +``` +{% endraw %} + +Above you can see a `collections` object was declared, which is made up of individual collection configurations. In this example, you are configuring a collection called `posts`. The renderer looks for a root directory called `_posts` within the `content` folder for individual pages to render. If you created another collection conf called `animals`, the renderer would look for a directory called `_animals` for content files to render. + +Each configuration item is made up of a few parts: +- `output` + - **required**: false + - **type**: `boolean` + - **description**: This optional attribute determines whether the collections should render or not. When set to `false`, virtual routes for the collection are not created. +- `route` + - **required**: true + - **type**: `string` + - **default**: `none` + - **description**: The `route` attribute is required and tells the renderer what pattern to generate collection routes from. A collection route should always include at least one valid dynamic namespace that uniquely identifies each collection member. + - Any namespace in the route declaration which begins with `:` is considered dynamic. + - Only certain dynamic namespaces are recognized by Kong as valid: + - `:title`: Replaces namespace with a contents `title`, declared in headmatter. + - `:name`: Replaces namespace with the filename of a piece of content. + - `:collection`: Replaces namespace with name of current collection. + - `:stub`: Replaces namespace with value of `headmatter.stub` in each contents headmatter. +- `layout` + - **required**: true + - **type**: `string` + - **description**: The `layout` attribute determines what HTML layout the collections use to render. The path root is accessed from within the current themes `layouts` directory. + +### content/_posts/post1.md + +{% raw %} +``` +--- +title: Post One +stub: blog +--- + +This is my first post! +``` +{% endraw %} + + +### content/_posts/post2.md + +{% raw %} +``` +--- +title: Post Two +stub: blog +--- + +This is my second post! +``` +{% endraw %} + +### themes/base/layouts/post.html + +{% raw %} +```html +

    {{ page.title }}

    +

    {* page.body *}

    +``` +{% endraw %} + +Output: + +From `/blog/posts/post1`: + +```html +

    Post One

    +

    This is my first post!

    +``` + +From `/blog/posts/post2`: + +```html +

    Post Two

    +

    This is my second post!

    +``` + + +## Kong Template Helpers - Lua API +Kong Template Helpers are a collection of objects that give access to your portal data at the time of render and provide powerful integrations into Kong. + +Global: + +- [`l`](#lkey-fallback) - Locale helper, first version, gets values from the currently active page. +- [`each`](#eachlist_or_table) - Commonly used helper to iterate over lists or tables. +- [`print`](#printany) - Commonly used helper to print lists / tables. +- [`markdown`](#printany) - Commonly used helper to print lists / tables. +- [`json_decode`](#json_decode) - Decode JSON to Lua table. +- [`json_encode`](#json_encode) - Encode Lua table to JSON. + +Objects: + +- [`portal`](#portal) - The portal object refers to the current workspace portal being accessed. +- [`page`](#page) - The page object refers to the currently active page and its contents. +- [`user`](#user) - The user object represents the currently logged in developer accessing the Kong Portal. +- [`theme`](#theme) - The theme object represents the currently active theme and its variables. +- [`tbl`](#tbl) = Table helper methods. Examples: `map`, `filter`, `find`, `sort`. +- [`str`](#str) = String helper methods. Examples: `lower`, `upper`, `reverse`, `endswith`. +- [`helpers`](#helpers) - Helper functions simplify common tasks or provide easy shortcuts to Kong Portal methods. + + +Terminology / Definitions: + +- `list` - Also referred to commonly as an array (`[1, 2, 3]`) in Lua is a table-like object (`{1, 2, 3}`). Lua list index starts at `1` not `0`. Values can be accessed by array notation (`list[1]`). +- `table` - Also commonly known as an object or HashMap (`{1: 2}`) in Lua looks like (`{1 = 2}`). Values can be accessed by array or dot notation (`table.one or table["one"]`). + +### l(key, fallback) + +Returns the current translation by key from the currently active page. + +#### Return Type +{% raw %} + +```lua +string +``` +{% endraw %} + +#### Usage + +Using `content/en/example.txt`: + +{% raw %} +```yaml +--- +layout: example.html + +locale: + title: Welcome to {{portal.name}} + slogan: The best developer portal ever created. +--- +``` +{% endraw %} + + +Using `content/es/example.txt`: + +{% raw %} +```yaml +--- +layout: example.html + +locale: + title: Bienvenido a {{portal.name}} + slogan: El mejor portal para desarrolladores jamás creado. +--- +``` +{% endraw %} + + +Using `layouts/example.html`: + +{% raw %} +```lua +

    {* l("title", "Welcome to" .. portal.name) *}

    +

    {* l("slogan", "My amazing developer portal!") *}

    +

    {* l("powered_by", "Powered by Kong.") *}

    +``` +{% endraw %} + + +Output: + +For `en/example`: + +{% raw %} +```html +

    Welcome to Kong Portal

    +

    The best developer portal ever created.

    +

    Powered by Kong.

    +``` +{% endraw %} + + +For `es/example`: + +{% raw %} +```html +

    Bienvenido a Kong Portal

    +

    El mejor portal para desarrolladores jamás creado.

    +

    Powered by Kong.

    +``` +{% endraw %} + + +#### Notes + +- `l(...)` is a helper from the `page` object. It can be also accessed via `page.l`. However, `page.l` does not support template interpolation (for example, `{{portal.name}}` will not work.) + +### each(list_or_table) + +Returns the appropriate iterator depending on what type of argument is passed. + +#### Return Type + +```lua +Iterator +``` + +#### Usage + +Template (List): + +{% raw %} +```lua +{% for index, value in each(table) do %} +
      +
    • Index: {{index}}
    • +
    • Value: {{ print(value) }}
    • +
    +{% end %} +``` +{% endraw %} + + +Template (Table): + +{% raw %} +```lua +{% for key, value in each(table) do %} +
      +
    • Key: {{key}}
    • +
    • Value: {{ print(value) }}
    • +
    +{% end %} +``` +{% endraw %} + +### print(any) + +Returns the output of an input value as a string. + +#### Return Type + +```lua +string +``` + +#### Usage + +Template (Table): + +{% raw %} +```lua +
    {{print(page)}}
    +``` +{% endraw %} + +### markdown(string) + +Returns HTML from the markdown string passed as an argument. If a string argument is not valid markdown, the function will return the string as is. To render properly, the helper should be used with raw `{* *}` delimiters. + +#### Return Type + +```lua +string +``` + +#### Usage + +Template (string as an argument): + +{% raw %} +```lua +
    {* markdown("##This is Markdown") *}
    +``` +{% endraw %} + +Template (content val as an argument): + +{% raw %} +```lua +
    {* markdown(page.description) *}
    +``` +{% endraw %} + +### json_encode(object) + +JSON encodes Lua table passed as argument + +#### Return Type + +```lua +string +``` + +#### Usage + +Template: + +{% raw %} +```lua +
    {{ json_encode({ dog = cat }) }}
    +``` +{% endraw %} + +### json_decode(string) + +Decodes JSON string argument to Lua table + +#### Return Type + +```lua +table +``` + +#### Usage + +Template: + +{% raw %} +```lua +
    {{ print(json_encode('{"dog": "cat"}')) }}
    +``` +{% endraw %} + +### portal + +`portal` gives access to data relating to the current portal, this includes things like portal configuration, content, specs, and layouts. + + - [`portal.workspace`](#portalworkspace) + - [`portal.url`](#portalurl) + - [`portal.api_url`](#portalapi_url) + - [`portal.auth`](#portalauth) + - [`portal.specs`](#portalspecs) + - [`portal.specs_by_tag`](#portalspecs_by_tag) + - [`portal.developer_meta_fields`](#portaldeveloper_meta_fields) + +You can access the current workspace portal config directly on the `portal` object like so: + +```lua +portal[config_key] or portal.config_key +``` + +For example `portal.auth` is a portal config value. You can find a list of config values by reading the portal section of `kong.conf`. + +#### From kong.conf + +The portal only exposes config values that start with `portal_`, and they can be access by removing the `portal_` prefix. + +Some configuration values are modified or customized, these customizations are documented under the [Portal Members](#portal-members) section. + +##### portal.workspace + +Returns the current portal's workspace. + +##### Return Type + +```lua +string +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{portal.workspace}} +``` +{% endraw %} + +Output: + +```html +default +``` + +#### portal.url + +Returns the current portal's url with workspace. + +##### Return Type + +```lua +string +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{portal.url}} +``` +{% endraw %} + +Output: + +```html +http://127.0.0.1:8003/default +``` + +#### portal.api_url + +Returns the configuration value for `portal_api_url` with +the current workspace appended. + +##### Return Type + +```lua +string or nil +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{portal.api_url}} +``` +{% endraw %} + +Output when `portal_api_url = http://127.0.0.1:8004`: + +```html +http://127.0.0.1:8004/default +``` + +#### portal.auth + +Returns the current portal's authentication type. + +##### Return Type + +```lua +string +``` + +##### Usage + +**Printing a value** + +Input: + +{% raw %} +```hbs +{{portal.auth}} +``` +{% endraw %} + +Output when `portal_auth = basic-auth`: + +```html +basic-auth +``` + +**Checking if authentication is enabled** + +Input: + +{% raw %} +```hbs +{% if portal.auth then %} + Authentication is enabled! +{% end %} +``` +{% endraw %} + +Output when `portal_auth = basic-auth`: + +```html +Authentication is enabled! +``` + +#### portal.specs + +Returns an array of specification files contained within the current portal. + +##### Return type + +```lua +array +``` + +##### Usage + +**Viewing a content value** + +Template: + +{% raw %} +```hbs +
    {{ print(portal.specs) }}
    +``` +{% endraw %} + +Output: + +```lua +{ + { + "path" = "content/example1_spec.json", + "content" = "..." + }, + { + "path" = "content/documentation/example1_spec.json", + "content" = "..." + }, + ... +} +``` + +**Looping through values** + +Template: + +{% raw %} +```hbs +{% for _, spec in each(portal.specs) %} +
  • {{spec.path}}
  • +{% end %} +``` +{% endraw %} + +Output: + +```hbs +
  • content/example1_spec.json
  • +
  • content/documentation/example1_spec.json
  • +``` + +**Filter by path** + +Template: + +{% raw %} +```hbs +{% for _, spec in each(helpers.filter_by_path(portal.specs, "content/documentation")) %} +
  • {{spec.path}}
  • +{% end %} +``` +{% endraw %} + +Output: + +```hbs +
  • content/documentation/example1_spec.json
  • +``` + +#### portal.developer_meta_fields + +Returns an array of developer meta fields available/required by Kong to register a developer. + +#### Return Type + +```lua +array +``` + +##### Usage + +**Printing a value** + +Template: + +{% raw %} +```hbs +{{ print(portal.developer_meta_fields) }} +``` +{% endraw %} + +Output: + +{% raw %} +```lua +{ + { + label = "Full Name", + name = "full_name", + type = "text", + required = true, + }, + ... +} +``` +{% endraw %} + +**Looping through values** + +Template: + +{% raw %} +```hbs +{% for i, field in each(portal.developer_meta_fields) do %} +
      +
    • Label: {{field.label}}
    • +
    • Name: {{field.name}}
    • +
    • Type: {{field.type}}
    • +
    • Required: {{field.required}}
    • +
    +{% end %} +``` +{% endraw %} + +Output: + +```html +
      +
    • Label: Full Name
    • +
    • Name: full_name
    • +
    • Type: text
    • +
    • Required: true
    • +
    +... +``` + +### page + +`page` gives access to data relating to the current page, which includes things like page url, path, breadcrumbs, and more. + + - [`page.route`](#pageroute) + - [`page.url`](#pageurl) + - [`page.breadcrumbs`](#pagebreadcrumbs) + - [`page.body`](#pagebody) + +When you create a new content page, you are able to define key-values. Here you are going to learn how to access those values and a few other interesting things. + +You can access the key-values you define directly on the `page` object like so: + +{% raw %} +```lua +page[key_name] or page.key_name +``` +{% endraw %} + +You can also access nested keys like so: + +```lua +page.key_name.nested_key +``` +{% raw %} +Be careful! To avoid output errors, make sure that the `key_name` exists before accessing `nested_key` as shown below: +```hbs +{{page.key_name and page.key_name.nested_key}} +``` +{% endraw %} + +#### page.route + +Returns the current page's route/path. + +##### Return Type + +```lua +string +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{page.route}} +``` +{% endraw %} + +Output, given url is `http://127.0.0.1:8003/default/guides/getting-started`: + +```html +guides/getting-started +``` + +#### page.url + +Returns the current page's url. + +##### Return Type + +```lua +string +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{page.url}} +``` +{% endraw %} + +Output, given url is `http://127.0.0.1:8003/default/guides/getting-started`: + +```html +http://127.0.0.1:8003/default/guides/getting-started +``` + +#### page.breadcrumbs + +Returns the current page's breadcrumb collection. + +##### Return Type + +```lua +table[] +``` + +##### Item Properties + +- `item.path` - Full path to item, no forward-slash prefix. +- `item.display_name` - Formatted name. +- `item.is_first` - Is this the first item in the list? +- `item.is_last` - Is this the last item in the list? + +##### Usage + +Template: + +{% raw %} +```hbs + +``` +{% endraw %} + +#### page.body + +Returns the body of the current page as a string. If the route's content file has a `.md` or `.markdown` extension, the body will be parsed from markdown to HTML. + +##### Return Type + +```lua +string +``` + +##### Usage for .txt, .json, .yaml, .yml templates + +`index.txt`: + +```hbs +This is text content. +``` + +Template: +{% raw %} +```hbs +

    This is a title

    +

    {{ page.body) }}

    +``` +{% endraw %} + +Output: +``` +> # This is a title +> This is text content. +``` + +##### Usage for .md, .markdown templates + +Template (markdown): +Use the raw delimiter syntax `{* *}` to render markdown within a template. + +`index.txt` +```hbs +# This is a title +This is text content. +``` + +Template: +```hbs +{* page.body *} +``` + +Output: +``` +> # This is a title +> This is text content. +``` + +### user + +`user` gives access to data relating to the currently authenticated user. User object is only applicable when `KONG_PORTAL_AUTH` is enabled. + + - [`user.is_authenticated`](#useris_authenticated) + - [`user.has_role`](#userhas_role) + - [`user.get`](#userget) + + +#### user.is_authenticated + +Returns `boolean` value as to the current user's authentication status. + +##### Return Type + +```lua +boolean +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{print(user.is_authenticated)}} +``` +{% endraw %} + +Output: + +```html +true +``` + +#### user.has_role + +Returns `true` if a user has a role given as an argument. + +##### Return Type + +```lua +boolean +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{print(user.has_role("blue"))}} +``` +{% endraw %} + +Output: + +```html +true +``` + +#### user.get + +Takes developer attribute as an argument and returns value if present. + +##### Return Type + +```lua +any +``` + +##### Usage + +Template: + +{% raw %} +```hbs +{{user.get("email")}} +{{print(user.get("meta"))}} +``` +{% endraw %} + +Output: + +```html +example123@konghq.com +{ "full_name" = "example" } +``` + + +### theme + +The `theme` object exposes values set in your `theme.conf.yaml` file. In addition, any variable overrides contained in `portal.conf.yaml` will be included as well. + + - [`theme.colors`](#usercolors) + - [`theme.color`](#usercolor) + - [`theme.fonts`](#userfonts) + - [`theme.font`](#userfont) + + +#### theme.colors + +Returns a table of color variables and their values as key-value pairs. + +##### Return Type + +```lua +table +``` + +##### Usage + +`theme.conf.yaml`: + +```yaml +name: Kong +colors: + primary: + value: '#FFFFFF' + description: 'Primary Color' + secondary: + value: '#000000' + description: 'Secondary Color' + tertiary: + value: '#1DBAC2' + description: 'Tertiary Color' +``` + +Template: + +{% raw %} +```lua +{% for k,v in each(theme.colors) do %} +

    {{k}}: {{v}}

    +{% end %} +``` +{% endraw %} + +Output: + +```html +

    primary: #FFFFFF

    +

    secondary: #000000

    +

    tertiary: #1DBAC2

    +``` + +#### theme.color + +Description + +Takes color var by string argument, returns value. + +##### Return Type + +```lua +string +``` + +##### Usage + +`theme.conf.yaml`: + +```yaml +name: Kong +colors: + primary: + value: '#FFFFFF' + description: 'Primary Color' + secondary: + value: '#000000' + description: 'Secondary Color' + tertiary: + value: '#1DBAC2' + description: 'Tertiary Color' +``` + +Template: + +{% raw %} +```lua +

    primary: {{theme.color("primary")}}

    +

    secondary: {{theme.color("secondary")}}

    +

    tertiary: {{theme.color("tertiary")}}

    +``` +{% endraw %} + +Output: + +```html +

    primary: #FFFFFF

    +

    secondary: #000000

    +

    tertiary: #1DBAC2

    +``` + + +#### theme.fonts + +Returns table of font vars and their values as key-value pairs. + +##### Return Type + +```lua +table +``` + +##### Usage + +`theme.conf.yaml`: + +```yaml +name: Kong +fonts: + base: Roboto + code: Roboto Mono + headings: Lato +``` + +Template: + +{% raw %} +```lua +{% for k,v in each(theme.fonts) do %} +

    {{k}}: {{v}}

    +{% end %} +``` +{% endraw %} + +Output: + +```html +

    base: Roboto

    +

    code: Roboto Mono

    +

    headings: Lato

    +``` + +#### theme.font + +Takes font name by string argument, returns value. + +##### Return Type + +```lua +string +``` + +##### Usage + +`theme.conf.yaml`: + +```yaml +name: Kong +fonts: + base: Roboto + code: Roboto Mono + headings: Lato +``` + +Template: + +{% raw %} +```lua +

    base: {{theme.font("base")}}

    +

    code: {{theme.font("code")}}

    +

    headings: {{theme.font("headings")}}

    +``` +{% endraw %} + +Output: + +```html +

    base: #FFFFFF

    +

    code: #000000

    +

    headings: #1DBAC2

    +``` + +### str + +Table containing useful string helper methods. + +#### Usage + +`.upper()` example: + +{% raw %} +```lua +
    {{ str.upper("dog") }}
    +``` +{% endraw %} + +#### Methods + +##### str.[byte](https://www.gammon.com.au/scripts/doc.php?lua=string.byte) +##### str.[char](https://www.gammon.com.au/scripts/doc.php?lua=string.char) +##### str.[dump](https://www.gammon.com.au/scripts/doc.php?lua=string.dump) +##### str.[find](https://www.gammon.com.au/scripts/doc.php?lua=string.find) +##### str.[format](https://www.gammon.com.au/scripts/doc.php?lua=string.format) +##### str.[gfind](https://www.gammon.com.au/scripts/doc.php?lua=string.gfind) +##### str.[gmatch](https://www.gammon.com.au/scripts/doc.php?lua=string.gmatch) +##### str.[gsub](https://www.gammon.com.au/scripts/doc.php?lua=string.gsub) +##### str.[len](https://www.gammon.com.au/scripts/doc.php?lua=string.len) +##### str.[lower](https://www.gammon.com.au/scripts/doc.php?lua=string.lower) +##### str.[match](https://www.gammon.com.au/scripts/doc.php?lua=string.match) +##### str.[rep](https://www.gammon.com.au/scripts/doc.php?lua=string.rep) +##### str.[reverse](https://www.gammon.com.au/scripts/doc.php?lua=string.reverse) +##### str.[sub](https://www.gammon.com.au/scripts/doc.php?lua=string.sub) +##### str.[upper](https://www.gammon.com.au/scripts/doc.php?lua=string.upper) +##### str.[isalpha](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isalpha) +##### str.[isdigit](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isdigit) +##### str.[isalnum](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isalnum) +##### str.[isspace](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isspace) +##### str.[islower](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#islower) +##### str.[isupper](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#isupper) +##### str.[startswith](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#startswith) +##### str.[endswith](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#endswith) +##### str.[join](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#join) +##### str.[splitlines](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#splitlines) +##### str.[split](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#split) +##### str.[expandtabs](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#expandtabs) +##### str.[lfind](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#lfind) +##### str.[rfind](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#rfind) +##### str.[replace](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#replace) +##### str.[count](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#count) +##### str.[ljust](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#ljust) +##### str.[rjust](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#rjust) +##### str.[center](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#center) +##### str.[lstrip](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#lstrip) +##### str.[rstrip](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#rstrip) +##### str.[strip](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#strip) +##### str.[splitv](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#splitv) +##### str.[partition](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#partition) +##### str.[rpartition](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#rpartition) +##### str.[at](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#at) +##### str.[lines](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#lines) +##### str.[title](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#title) +##### str.[shorten](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#shorten) +##### str.[quote_string](https://stevedonovan.github.io/Penlight/api/libraries/pl.stringx.html#quote_string) + + +### tbl + +Table containing useful table helper methods + +#### Usage + +`.map()` example: +{% raw %} +```lua +{% tbl.map({"dog", "cat"}, function(item) %} + {% if item ~= "dog" then %} + {% return true %} + {% end %} +{% end) %} +``` +{% endraw %} + +#### Methods + +##### tbl.[getn](https://www.gammon.com.au/scripts/doc.php?lua=table.getn) +##### tbl.[setn](https://www.gammon.com.au/scripts/doc.php?lua=table.setn) +##### tbl.[maxn](https://www.gammon.com.au/scripts/doc.php?lua=table.maxn) +##### tbl.[insert](https://www.gammon.com.au/scripts/doc.php?lua=table.insert) +##### tbl.[remove](https://www.gammon.com.au/scripts/doc.php?lua=table.remove) +##### tbl.[concat](https://www.gammon.com.au/scripts/doc.php?lua=table.concat) +##### tbl.[map](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#map) +##### tbl.[foreach](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#foreach) +##### tbl.[foreachi](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#foreachi) +##### tbl.[sort](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#sort) +##### tbl.[sortv](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#sortv) +##### tbl.[filter](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#filter) +##### tbl.[size](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#size) +##### tbl.[index_by](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#index_by) +##### tbl.[transform](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#transform) +##### tbl.[range](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#range) +##### tbl.[reduce](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#reduce) +##### tbl.[index_map](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#index_map) +##### tbl.[makeset](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#makeset) +##### tbl.[union](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#union) +##### tbl.[intersection](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#intersection) +##### tbl.[count_map](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#count_map) +##### tbl.[set](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#set) +##### tbl.[new](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#new) +##### tbl.[clear](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#clear) +##### tbl.[removevalues](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#removevalues) +##### tbl.[readonly](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#readonly) +##### tbl.[update](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#update) +##### tbl.[copy](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#copy) +##### tbl.[deepcopy](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#deepcopy) +##### tbl.[icopy](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#icopy) +##### tbl.[move](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#move) +##### tbl.[insertvalues](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#insertvalues) +##### tbl.[deepcompare](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#deepcompare) +##### tbl.[compare](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#compare) +##### tbl.[compare_no_order](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#compare_no_order) +##### tbl.[find](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#find) +##### tbl.[find_if](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#find_if) +##### tbl.[search](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#search) +##### tbl.[keys](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#keys) +##### tbl.[values](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#values) +##### tbl.[sub](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#sub) +##### tbl.[merge](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#merge) +##### tbl.[difference](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#difference) +##### tbl.[zip](https://stevedonovan.github.io/Penlight/api/libraries/pl.tablex.html#zip) + \ No newline at end of file diff --git a/app/gateway/2.7.x/get-started/comprehensive/dev-portal.md b/app/gateway/2.7.x/get-started/comprehensive/dev-portal.md new file mode 100644 index 000000000000..aacfac2ebd9e --- /dev/null +++ b/app/gateway/2.7.x/get-started/comprehensive/dev-portal.md @@ -0,0 +1,100 @@ +--- +title: Publish, Locate, and Consume Services +badge: enterprise +--- + +Dev Portal provides a single source of truth for all developers to locate, access, and consume services. With intuitive content management for documentation, streamlined developer onboarding, and role-based access control (RBAC), the Dev Portal provides a comprehensive solution for creating and customizing a unified developer experience. + +## Before you begin + +Make sure the Dev Portal is on. You should have enabled it during [installation](/gateway/{{page.release}}/install-and-run/). + +## Enable the Dev Portal for a Workspace + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. In Kong Manager, open the Workspaces tab and open your workspace (for example, SecureWorkspace). + +2. Scroll down in the sidebar, then click the **Overview** link under the Dev Portal section. + +3. Click **Enable Developer Portal** and refresh the browser page. + +{% endnavtab %} +{% navtab Using the Admin API %} + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X PATCH http://localhost:8001/workspaces/SecureWorkspace \ + --data config.portal=true +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f PATCH http://localhost:8001/workspaces/SecureWorkspace \ + config.portal=true +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% endnavtabs %} +This will expose the Dev Portal at `http://localhost:8003/SecureWorkspace.` + +After the Dev Portal is enabled for the Workspace, a few new links appear in the left navigation menu. It may take a few seconds for the Settings page to populate. + +You can learn more about personalization in the [Dev Portal documentation](/gateway/{{page.release}}/developer-portal/), including: + +* [Customizing the look and feel of the site and editor](/gateway/{{page.release}}/developer-portal/theme-customization/easy-theme-editing/) +* [Managing access](/gateway/{{page.release}}/developer-portal/administration/managing-developers/) +* [Configuring the Dev Portal](/gateway/{{page.release}}/developer-portal/configuration/workspaces/) + +## Access and Interact with the Dev Portal + +1. Go back to **Dev Portal** > **Overview** and open the link in a new tab, or open the Dev Portal directly using this URL: `http://localhost:8003/SecureWorkspace`. + + You’ll see a list of available API catalogs. By default, *httpbin.org* and *Swagger Petstore* appear as examples. + +2. Click on the **httpbin.org** entry to explore the API. + + On the left side, tags for the API as configured by the spec are displayed for easy searching. + + On the right, you can see the HTTP methods of the API. Clicking into each method shows its details, lets you test the method, and provides code snippets developers can use to leverage the method in their applications. + +3. Test the GET method: + + 1. Under **HTTP Methods**, click the GET method. + 2. Click **Try it Out**, then click **Execute**. Review the results of the response. + +## Publish a Spec to Dev Portal + +In this section, you’re going to add a new spec, the *Kong Vitals API*, to the Dev Portal catalog. The Kong Vitals API shows how {{site.base_gateway}} and connected APIs are performing. + +1. In Kong Manager, navigate to **Dev Portal** > **Editor** and open the link in a new tab. The editor lets you customize the Dev Portal. + +2. Click on **New File +** to add a new spec. + +3. In the New File dialog, open the dropdown and select **spec**, then name the spec `vitals_spec.yaml`. + +4. Click on **Create File**. + + The editor creates the file and prepares it for editing. Since you haven’t added any content to the file, the preview displays “Unable to render this definition”. + +5. In another tab, open the [Kong Vitals Overview page](/gateway/{{page.release}}/vitals/#using-vitals-api) to download the `vitalsSpec.yaml.` Open it in your favorite text editor and copy the contents of the file. + +6. In the Dev Portal editor, clear the contents of the editor, then paste the contents of `vitalsSpec.yaml`. + +7. Click **Save Changes**. If done correctly, the preview should show the API now. + +8. View the Dev Portal at `http://localhost:8003/SecureWorkspace` and notice the new spec published to the Dev Portal. + +## Summary + +In this topic, you: + +* Enabled the Dev Portal on the Workspace `SecureWorkspace`. +* Tested the httpbin `GET` method. +* Added a new spec for the Kong Vitals API to the Dev Portal catalog. diff --git a/app/gateway/2.7.x/get-started/comprehensive/expose-services.md b/app/gateway/2.7.x/get-started/comprehensive/expose-services.md new file mode 100644 index 000000000000..d36ae859bea1 --- /dev/null +++ b/app/gateway/2.7.x/get-started/comprehensive/expose-services.md @@ -0,0 +1,332 @@ +--- +title: Expose your Services with Kong Gateway +--- + +In this topic, you’ll learn how to expose your Services using Routes. + +If you are following the Getting Started workflow, make sure you have completed +[Prepare to Administer {{site.base_gateway}}](/gateway/{{page.release}}/get-started/comprehensive/prepare) +before moving on. + +If you are not following the Getting Started workflow, make sure you have +{{site.base_gateway}} installed and started. + +## What are Services and Routes? + +**Service** and **Route** objects let you expose your services to clients with +{{site.base_gateway}}. When configuring access to your API, you’ll start by specifying a +Service. In {{site.base_gateway}}, a Service is an entity representing an external +upstream API or microservice — for example, a data transformation +microservice, a billing API, and so on. + +The main attribute of a Service is its **URL**, where the service listens for +requests. You can specify the URL with a single string, or by specifying its +protocol, host, port, and path individually. + +Before you can start making requests against the Service, you will need to add +a Route to it. Routes determine how (and if) requests are sent to their Services +after they reach {{site.base_gateway}}. A single Service can have many Routes. + +After configuring the Service and the Route, you’ll be able to start making +requests through {{site.base_gateway}}. + +This diagram illustrates the flow of requests and responses being routed through +the Service to the backend API. + +![Services and routes](/assets/images/products/gateway/getting-started-guide/route-and-service.png) + +## Add a Service + +For the purpose of this example, you’ll create a Service pointing to the httpbin +API. Httpbin is an “echo” type public website that returns requests back to the +requester as responses. This visualization will be helpful for learning how Kong +Gateway proxies API requests. + +{{site.base_gateway}} exposes the RESTful Admin API on port `8001`. The gateway’s +configuration, including adding Services and Routes, is done through requests to +the Admin API. + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. On the Workspaces tab in Kong Manager, scroll to the Workspace section and +click the **default** workspace. + + This example uses the default workspace, but you can also create a new + workspace, or use an existing workspace. + +2. Scroll down to **Services** and click **Add a Service**. + +3. In the **Create Service** dialog, enter the name `example_service` and the +URL `https://httpbin.konghq.com`. + +4. Click **Create**. + +The service is created, and the page automatically redirects back to the +`example_service` overview page. +{% endnavtab %} +{% navtab Using the Admin API %} + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/services \ + --data name=example_service \ + --data url='https://httpbin.konghq.com' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http POST :8001/services \ + name=example_service \ + url='https://httpbin.konghq.com' +``` +{% endnavtab %} +{% endnavtabs %} + + +If the service is created successfully, you'll get a 201 success message. + +Verify the service’s endpoint: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i http://localhost:8001/services/example_service +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/services/example_service +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +1. In the `kong.yaml` file you exported in +[Prepare to Administer {{site.base_gateway}}](/gateway/{{page.release}}/get-started/comprehensive/prepare/#verify-the-kong-gateway-configuration), +define a Service with the name `example_service` and the URL +`https://httpbin.konghq.com`: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + ``` +2. Save the file. From your terminal, sync the configuration to update your +gateway instance: + + ``` bash + deck sync + ``` + + The message should show that you’re creating a service: + + ``` + creating service example_service + Summary: + Created: 1 + Updated: 0 + Deleted: 0 + ``` + +{% endnavtab %} +{% endnavtabs %} + +## Add a Route + +For the Service to be accessible through the API gateway, you need to add a +Route to it. + +{% navtabs %} +{% navtab Using Kong Manager %} +1. From the `example_service` overview page, scroll down to the Routes section +and click **Add Route**. + + The Create Route dialog displays with the Service field auto-populated with + the Service name and ID number. This field is required. + + **Note:** If the Service field is not automatically populated, click + **Services** in the left navigation pane. Find your Service, click the + clipboard icon next to the id field, then go back to the Create Route + page and paste it into the Service field. + +2. Enter a name for the Route, and at least one of the following fields: Host, +Methods, or Paths. For this example, use the following: + 1. For **Name**, enter `mocking`. + 2. For **Path(s)**, click **Add Path** and enter `/mock`. + +3. Click **Create**. + +The Route is created and you are automatically redirected back to the +`example_service` overview page. The new Route appears under the Routes section. + +{% endnavtab %} +{% navtab Using the Admin API %} + +Define a Route (`/mock`) for the Service (`example_service`) with a specific +path that clients need to request. Note at least one of the hosts, paths, or +methods must be set for the Route to be matched to the service. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/services/example_service/routes \ + --data 'paths[]=/mock' \ + --data name=mocking +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/services/example_service/routes \ + paths:='["/mock"]' \ + name=mocking +``` +{% endnavtab %} +{% endnavtabs %} + + +A `201` message indicates the Route was created successfully. + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +1. Paste the following into the `kong.yaml` file, under the entry for +`example_service`: + + ``` yaml + routes: + - name: mocking + paths: + - /mock + strip_path: true + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + ``` + +2. Sync the configuration: + + ``` bash + deck sync + ``` + +3. (Optional) You can update your local file with the new configuration: + + {:.important} + > **Be careful!** Any subsequent `deck dump` will + overwrite the existing `kong.yaml` file. Create backups as needed. + + ``` bash + $ deck dump + ``` + + Alternatively, you will also see this configuration in the diff that decK + shows when you're syncing a change to the configuration. + + You'll notice that both the Service and Route now have parameters that you + did not explicitly set. These are default parameters that every Service and + Route are created with: + + ``` yaml + services: + - connect_timeout: 60000 + host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + read_timeout: 60000 + retries: 5 + write_timeout: 60000 + routes: + - name: mocking + paths: + - /mock + path_handling: v0 + preserve_host: false + protocols: + - http + - https + regex_priority: 0 + strip_path: true + https_redirect_status_code: 426 + ``` + + You can do this after any `deck sync` to see {{site.base_gateway}}'s most + recent configuration. + + The rest of this guide continues using the simplified version of the + configuration file without performing a `deck dump` for every step, to keep + it easy to follow. + +{% endnavtab %} +{% endnavtabs %} + +## Verify the Route is forwarding requests to the Service + +{% navtabs %} +{% navtab Using a Web Browser %} + +By default, {{site.base_gateway}} handles proxy requests on port `:8000`. + +From a web browser, enter `http://localhost:8000/mock`. + +{% endnavtab %} +{% navtab Using the Admin API %} + +Using the Admin API, issue the following: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X GET http://localhost:8000/mock/anything +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock/anything +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% endnavtabs %} + + +## Summary and next steps + +In this section, you: + +* Added a Service named `example_service` with a URL of `https://httpbin.konghq.com`. +* Added a Route named `/mock`. +* This means if an HTTP request is sent to the {{site.base_gateway}} node on +port `8000`(the proxy port) and it matches route `/mock`, then that request is +sent to `https://httpbin.konghq.com`. +* Abstracted a backend/upstream service and put a route of your choice on the +front end, which you can now give to clients to make requests. + +Next, go on to learn about [enforcing rate limiting](/gateway/{{page.release}}/get-started/comprehensive/protect-services/). diff --git a/app/gateway/2.7.x/get-started/comprehensive/improve-performance.md b/app/gateway/2.7.x/get-started/comprehensive/improve-performance.md new file mode 100644 index 000000000000..23d1f59e948e --- /dev/null +++ b/app/gateway/2.7.x/get-started/comprehensive/improve-performance.md @@ -0,0 +1,200 @@ +--- +title: Improve Performance with Proxy Caching +--- + +In this topic, you’ll learn how to use proxy caching to improve response efficiency using the Proxy Caching plugin. + +If you are following the getting started workflow, make sure you have completed [Protect your Services](/gateway/{{page.release}}/get-started/comprehensive/protect-services/) before continuing. + +## What is Proxy Caching? + +{{site.base_gateway}} delivers fast performance through caching. The Proxy Caching plugin provides this fast performance using a reverse proxy cache implementation. It caches response entities based on the request method, configurable response code, content type, and can cache per Consumer or per API. + +Cache entities are stored for a configurable period of time. When the timeout is reached, the gateway forwards the request to the Upstream, caches the result and responds from cache until the timeout. The plugin can store cached data in memory, or for improved performance, in Redis. + +## Why use Proxy Caching? + +Use proxy caching so that Upstream services are not bogged down with repeated requests. With proxy caching, {{site.base_gateway}} can respond with cached results for better performance. + +## Set up the Proxy Caching plugin + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Access your Kong Manager instance and your **default** workspace. + +2. Go to **API Gateway** and click **Plugins**. + +3. Click **New Plugin**. + +4. Scroll down to the Traffic Control section and find the **Proxy Caching** plugin. + +5. Click **Enable**. + +6. Select to apply the plugin as **Global**. This means that proxy caching applies to all requests. + +7. Scroll down and complete only the following fields with the parameters listed. + 1. config.cache_ttl: `30` + 2. config.content_type: `application/json; charset=utf-8` + 3. config.strategy: `memory` + + Besides the above fields, there may be others populated with default values. For this example, leave the rest of the fields as they are. + +8. Click **Create**. +{% endnavtab %} +{% navtab Using the Admin API %} + +Call the Admin API on port `8001` and configure plugins to enable in-memory caching globally, with a timeout of 30 seconds for Content-Type `application/json`. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/plugins \ + --data name=proxy-cache \ + --data config.content_type="application/json; charset=utf-8" \ + --data config.cache_ttl=30 \ + --data config.strategy=memory +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f :8001/plugins \ + name=proxy-cache \ + config.strategy=memory \ + config.cache_ttl=30 \ + config.content_type="application/json; charset=utf-8" +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +1. In the `plugins` section of your `kong.yaml` file, add the `proxy-cache` +plugin with a timeout of 30 seconds for Content-Type +`application/json; charset=utf-8`. + + ``` yaml + plugins: + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + +2. Sync the configuration: + + ```bash + deck sync + ``` + +{% endnavtab %} +{% endnavtabs %} + + +## Validate Proxy Caching + +Let’s check that proxy caching works. You'll need the Kong Admin API for this +step. + +Access the */mock* route using the Admin API and note the response headers: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X GET http://localhost:8000/mock/anything +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock/anything +``` +{% endnavtab %} +{% endnavtabs %} + + +In particular, pay close attention to the values of `X-Cache-Status`, `X-Kong-Proxy-Latency`, and `X-Kong-Upstream-Latency`: +``` +HTTP/1.1 200 OK +... +X-Cache-Key: d2ca5751210dbb6fefda397ac6d103b1 +X-Cache-Status: Miss +X-Content-Type-Options: nosniff +... +X-Kong-Proxy-Latency: 25 +X-Kong-Upstream-Latency: 37 +``` + +Next, access the */mock* route one more time. + +This time, notice the differences in the values of `X-Cache-Status`, `X-Kong-Proxy-Latency`, and `X-Kong-Upstream-Latency`. Cache status is a `hit`, which means {{site.base_gateway}} is responding to the request directly from cache instead of proxying the request to the Upstream service. + +Further, notice the minimal latency in the response, which allows {{site.base_gateway}} to deliver the best performance: + +``` +HTTP/1.1 200 OK +... +X-Cache-Key: d2ca5751210dbb6fefda397ac6d103b1 +X-Cache-Status: Hit +... +X-Kong-Proxy-Latency: 0 +X-Kong-Upstream-Latency: 1 +``` + +To test more rapidly, the cache can be deleted by calling the Admin API: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X DELETE http://localhost:8001/proxy-cache +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http delete :8001/proxy-cache +``` +{% endnavtab %} +{% endnavtabs %} + + +## Summary and Next Steps + +In this section, you: + +* Set up the Proxy Caching plugin, then accessed the `/mock` route multiple times to see caching in effect. +* Witnessed the performance differences in latency with and without caching. + +Next, you’ll learn about [securing services](/gateway/{{page.release}}/get-started/comprehensive/secure-services/). diff --git a/app/gateway/2.7.x/get-started/comprehensive/index.md b/app/gateway/2.7.x/get-started/comprehensive/index.md new file mode 100644 index 000000000000..d56aa0d59208 --- /dev/null +++ b/app/gateway/2.7.x/get-started/comprehensive/index.md @@ -0,0 +1,109 @@ +--- +title: Comprehensive Getting Started Guide +--- + +In this guide, you will: + +* Expose your services using Service and Route objects +* Set up rate limits and proxy caching +* Secure services with key authentication +* Load balance traffic + +If you have a license, you also have access +to Enterprise features. In addition to the basics above, +use this guide to: + +* Manage teams by setting up role-based access control (RBAC) +* Enable the Dev Portal to give your teams a central location to +publish, access, and consume services + +**{{site.ce_product_name}}**: an open-source, lightweight API gateway optimized +for microservices, delivering unparalleled latency, performance, and scalability. + If you just want the basics, this option will work for you. + +**{{site.base_gateway}}**: extends the {{site.base_gateway}} with Enterprise +features and support. It provides advanced functionality using plugins for +security, collaboration, performance at scale, and use of advanced protocols. + +## Concepts and Features in this guide + +Here’s the content covered in this guide, and how the pieces fit together: + +![Features in getting started guide](/assets/images/products/gateway/getting-started-guide/Kong-GS-overview.png) + +| Concept/Feature | Description {:width=75%:} | +|:------------------ |:--------------------------| +| Service | A Service object is the ID {{site.base_gateway}} uses to refer to the upstream APIs and microservices it manages. | +| Routes | Routes specify how (and if) requests are sent to their Services after they reach the API gateway. A single Service can have many Routes. | +| Consumers | Consumers represent end users of your API. Consumer objects let you control who can access your APIs. They also let you report on traffic using logging plugins and Kong Vitals. | +| Kong Manager | Kong Manager is the visual browser-based tool for monitoring and managing {{site.ee_product_name}}. | +| Admin API | {{site.base_gateway}} comes with an internal RESTful API for administration purposes. API commands can be run on any node in the cluster, and the configuration will apply consistently on all nodes. | +| Plugins | Plugins provide a modular system for modifying and controlling {{site.base_gateway}}’s capabilities. For example, to secure your API, you could require an access key, which you could set up using the key-auth plugin. Plugins provide a wide array of functionality, including access control, caching, rate limiting, logging, and more. | +| Rate Limiting plugin

    Rate Limiting Advanced plugin | This plugin lets you limit the number of HTTP requests a client can make within a given period of time.

    The advanced version of this plugin also provides sliding window support, and the ability to limit by header and service. | +| Proxy Caching plugin

    Proxy Caching Advanced plugin | This plugin provides a reverse proxy cache implementation. It caches response entities based on response code, content type, and request method for a given period of time.

    The advanced version of this plugin supports Redis and Redis Sentinel deployments. | +| Key Auth plugin

    Key Auth - Encrypted plugin | This plugin lets you add key authentication (also known as an API key) to a Service or a Route.

    The advanced version of this plugin stores the API keys in an encrypted format within the {{site.base_gateway}} data store. | +| Load Balancing | {{site.base_gateway}} provides two methods for load balancing: straightforward DNS-based or using a ring-balancer. In this guide, you’ll use a ring-balancer, which requires configuring upstream and target entities. With this method, the adding and removing of backend services is handled by {{site.base_gateway}}, and no DNS updates are necessary. | +| User Authorization (RBAC) | {{site.base_gateway}} handles user authorization through role-based access control (RBAC). Once enabled, RBAC lets you create teams and admins and assign them granular permissions either within a workspace, or across workspaces. | +| Dev Portal | The Dev Portal provides a single source of truth for all developers to locate, access, and consume services. | + + +## Understanding traffic flow in {{site.base_gateway}} + +{{site.base_gateway}} listens for traffic on its configured proxy port(s) `8000` +and `8443`, by default. It evaluates incoming client API requests and routes them +to the appropriate backend APIs. While routing requests and providing responses, +policies can be applied via plugins as necessary. + +For example, before routing a request, the client might be required to +authenticate. This delivers several benefits, including: + +* The service doesn’t need its own authentication logic since +{{site.base_gateway}} is handling authentication. +* The service only receives valid requests and therefore cycles are not wasted +processing invalid requests. +* All requests are logged for central visibility of traffic. + +![API Gateway traffic](/assets/images/products/gateway/getting-started-guide/gateway-traffic.png) + +## Before you begin + +Note the following before you start using this guide: + +### Installation + +* This guide assumes that you have {{site.ce_product_name}} +or {{site.base_gateway}} +[installed and running](/gateway/{{page.release}}/install-and-run/) on the platform of your choice. +* During your installation, take note of the `KONG_PASSWORD`; you’ll need it +later on in this guide for setting up user authorization. + +### Deployment guidelines + +* You can use this guide to get started in production environments, but this +guide does not provide all of the necessary configurations and security settings +that you would need for a production environment. +* The examples in this guide all use `` to refer to a +{{site.base_gateway}} instance's Admin API URL. Make sure to replace the +variable with the actual URL of your {{site.base_gateway}} installation. + + To find the URL, check the `admin_listen` property in the + `/etc/kong/kong.conf` file. + +### Using this guide + +* Throughout this guide, you will have the option to configure Kong in a few +different ways. Choose your preferred method, if options are available — +you don’t have to walk through all of them: + * Programmatically manage {{site.base_gateway}} using its REST-based Admin API + * Use the Kong Manager GUI *(Not available for open-source Gateway)* + * Use decK for declarative configuration (YAML) +* If you're running {{site.base_gateway}} in Hybrid mode, all tasks contained +in this guide take place on the Control Plane. +* This guide provides Kong Admin API examples in both HTTPie and cURL. If you +want to use HTTPie, install it from [here](https://httpie.org/). +* Any references to “{{site.base_gateway}}” refer to features or concepts +common to both {{site.ce_product_name}} and {{site.base_gateway}}. + +### Next Steps + +Next, [prepare to administer {{site.base_gateway}}](/gateway/{{page.release}}/get-started/comprehensive/prepare/). diff --git a/app/gateway/2.7.x/get-started/comprehensive/load-balancing.md b/app/gateway/2.7.x/get-started/comprehensive/load-balancing.md new file mode 100644 index 000000000000..b36c39acd2f7 --- /dev/null +++ b/app/gateway/2.7.x/get-started/comprehensive/load-balancing.md @@ -0,0 +1,199 @@ +--- +title: Set Up Intelligent Load Balancing +--- + +In this topic, you’ll learn about configuring upstream services, and create multiple targets for load balancing. + +If you are following the getting started workflow, make sure you have completed [Secure Services Using Authentication](/gateway/{{page.release}}/get-started/comprehensive/secure-services/) before moving on. + +## What are Upstreams? + +An **Upstream Object** refers to your upstream API/service sitting behind {{site.base_gateway}}, to which client requests are forwarded. In {{site.base_gateway}}, an Upstream Object represents a virtual hostname and can be used to health check, circuit break, and load balance incoming requests over multiple services (targets). + +In this topic, you’ll configure the service created earlier (`example_service`) to point to an upstream instead of the host. For the purposes of our example, the upstream will point to two different targets, `httpbin.konghq.com` and `httpbun.com`. In a real environment, the upstream will point to the same service running on multiple systems. + +Here is a diagram illustrating the setup: + +![Upstream targets](/assets/images/products/gateway/getting-started-guide/upstream-targets.png) + +## Why load balance across upstream targets? + +In the following example, you’ll use an application deployed across two different servers, or upstream targets. {{site.base_gateway}} needs to load balance across both servers, so that if one of the servers is unavailable, it automatically detects the problem and routes all traffic to the working server. + +## Configure Upstream Services + +In this section, you will create an Upstream named `example_upstream` and add two targets to it. + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Access your Kong Manager instance and your **default** workspace. +2. Go to **API Gateway** > **Upstreams**. +3. Click **New Upstream**. +4. For this example, enter `example_upstream` in the **Name** field. +5. Scroll down and click **Create**. +6. On the Upstreams page, find the new upstream service and click **View**. +7. Scroll down and click **New Target**. +8. In the target field, specify `httpbin.konghq.com` with port `80`, and click **Create**. +9. Create another target, this time for `httpbun.com` with port `80`. Click **Create**. +10. Open the **Services** page. +11. Find your `example_service` and click **Edit**. +12. Change the **Host** field to `example_upstream`, then click **Update**. +{% endnavtab %} +{% navtab Using the Admin API %} + +Call the Admin API on port `8001` and create an Upstream named `example_upstream`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/upstreams \ + --data name=example_upstream +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http POST :8001/upstreams \ + name=example_upstream +``` +{% endnavtab %} +{% endnavtabs %} + + +Update the service you created previously to point to this upstream: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X PATCH http://localhost:8001/services/example_service \ + --data host='example_upstream' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http PATCH :8001/services/example_service \ + host='example_upstream' +``` +{% endnavtab %} +{% endnavtabs %} + + +Add two targets to the upstream, each with port 80: `httpbun.com:80` and +`httpbin.konghq.com:80`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/upstreams/example_upstream/targets \ + --data target='httpbun.com:80' + +curl -X POST http://localhost:8001/upstreams/example_upstream/targets \ + --data target='httpbin.konghq.com:80' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http POST :8001/upstreams/example_upstream/targets \ + target=httpbun.com:80 +http POST :8001/upstreams/example_upstream/targets \ + target=httpbin.konghq.com:80 +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} + +{% navtab Using decK (YAML) %} +1. In your `kong.yaml` file, create an Upstream with two targets, each with port +80: `httpbun.com:80` and `httpbin.konghq.com:80`. + + ``` yaml + upstreams: + - name: example_upstream + targets: + - target: httpbin.konghq.com:80 + weight: 100 + - target: httpbun.com:80 + weight: 100 + ``` + +2. Update the service you created previously, pointing the `host` to this +Upstream: + + ``` yaml + services: + host: example_upstream + name: example_service + port: 80 + protocol: http + ``` + + After these updates, your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: example_upstream + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: key-auth + enabled: false + consumers: + - custom_id: consumer + username: consumer + keyauth_credentials: + - key: apikey + upstreams: + - name: example_upstream + targets: + - target: httpbin.konghq.com:80 + weight: 100 + - target: httpbun.com:80 + weight: 100 + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + +3. Sync the configuration: + + ``` bash + deck sync + ``` +{% endnavtab %} +{% endnavtabs %} + +You now have an Upstream with two targets, `httpbin.konghq.com` and `httpbun.com`, and a service pointing to that Upstream. + +## Validate the Upstream Services + +1. With the Upstream configured, validate that it’s working by visiting the route `http://localhost:8000/mock` using a web browser or CLI. +2. Continue hitting the endpoint and the site should change from `httpbin` to `httpbun`. + +## Summary and next steps + +In this topic, you: + +* Created an Upstream object named `example_upstream` and pointed the Service `example_service` to it. +* Added two targets, `httpbin.konghq.com` and `httpbun.com`, with equal weight to the Upstream. + +If you have a {{site.konnect_product_name}} subscription, go on to [Managing Administrative Teams](/gateway/{{page.release}}/get-started/comprehensive/manage-teams/). diff --git a/app/gateway/2.7.x/get-started/comprehensive/manage-teams.md b/app/gateway/2.7.x/get-started/comprehensive/manage-teams.md new file mode 100644 index 000000000000..fb49573abffe --- /dev/null +++ b/app/gateway/2.7.x/get-started/comprehensive/manage-teams.md @@ -0,0 +1,367 @@ +--- +title: Manage Administrative Teams +badge: enterprise +--- + +In this topic, you’ll learn how to manage and configure user authorization using workspaces and teams in {{site.base_gateway}}. + +If you are following the getting started workflow, make sure you have completed [Set Up Intelligent Load Balancing](/gateway/{{page.release}}/get-started/comprehensive/load-balancing/) before moving on. + +## Overview of workspaces and Teams + +Many organizations have strict security requirements. For example, organizations need the ability to segregate the duties of an administrator to ensure that a mistake or malicious act by one administrator doesn’t cause an outage. {{site.base_gateway}} provides a number of security capabilities to help customers secure the administration environment. + +**Workspaces** enable an organization to segment objects and admins into namespaces. The segmentation allows teams of admins sharing the same {{site.base_gateway}} cluster to adopt **roles** for interacting with specific objects. For example, one team (Team A) may be responsible for managing a particular service, whereas another team (Team B) may be responsible for managing another service. Teams should only have the roles they need to perform the administrative tasks within their specific workspaces. + +{{site.base_gateway}} does all of this through **Role-Based Access Control (RBAC)**. All administrators can be given specific roles, whether you are using Kong Manager or the Admin API, which control and limit the scope of administrative privileges within specific workspaces. + +In this example, you’ll start by creating a simple workspace called `SecureWorkspace`. Then, you’ll create an administrator for that workspace, with rights to administer only the objects in the SecureWorkspace and nothing else. + +>**Note:** The steps in this topic cannot be performed using declarative +configuration. + +## Securing your Gateway Installation + +At a high level, securing {{site.base_gateway}} administration is a two-step process: + +1. Turn on RBAC. +2. Create a workspace and an admin for segregated administration. + +At this point in the Getting Started Guide, you have been interacting with your environment as the built-in Super Admin, `kong_admin`. The password for this `kong_admin` user was “seeded” during the installation process using the KONG_PASSWORD environment variable. After RBAC is enabled, you will need to authenticate to the Kong Manager and the {{site.base_gateway}} Admin API using the proper credentials. + +In the following sections, you will need the `kong_admin` account’s password to log in to {{site.base_gateway}}, and the `kong_admin_uri` needs to be configured to avoid getting CORS errors. + +## Turn on RBAC + +{% include_cached /md/enterprise/turn-on-rbac.md %} + +## Create a workspace + +{% navtabs %} +{% navtab Using Kong Manager %} + +### Log into Kong Manager + +1. Go to Kong Manager, or reload the page if you already have it open and you will see the following login screen. +2. Log in to Kong Manager with the built-in Super Admin account, `kong_admin`, and its password. + + Remember, this is the initial KONG_PASSWORD you used when you ran migrations during installation. + +3. If you have logged in successfully, then you can start administering your {{site.base_gateway}} cluster. + + If this step did not work, and you know the credentials are correct, then something is likely wrong with your {{site.base_gateway}} configuration. Double-check the settings. If the cause of the problem still isn’t clear, work with your {{site.konnect_product_name}} account team and [Kong Support](https://support.konghq.com/) for assistance. + +#### Create the Workspace + +1. Access your Kong Manager instance. +2. On the workspaces tab, click on **New Workspace**. +3. Create a workspace named `SecureWorkspace` and select a color for the workspace avatar. + + **Note:** Each workspace name should be unique, regardless of letter case. For example, naming one workspace “Payments” and another one “payments” will create two different workspaces that appear identical. + + **WARNING:** Do not give a workspace the same name as any of these major routes in Kong Manager: + + |---------|-----------|--------------|---------------| + | Admins | APIs | Certificates | Consumers | + | Plugins | Portal | Routes | Services | + | SNIs | Upstreams | Vitals | PermalinkStep | + +4. Click **Create New workspace**. +5. On the new workspace, click **Teams**. +6. From the Teams page, click the **Roles** tab to view the default roles that come with {{site.base_gateway}}. +7. Next to SecureWorkspace, click **View** to see its assigned roles. +8. There are different roles available for the SecureWorkspace. By default, each new workspace has the following roles and privileges: + + | Role | Description | + |--------------------------|----------------------------------------------------------------------------------------------| + | *workspace-admin* | Can administer the objects in a workspace but can’t add new administrators to the workspace. | + | *workspace-portal-admin* | Can manage the Dev Portal. | + | *workspace-read-only* | Can view anything in the workspace, but can’t make any changes. | + | *workspace-super-admin* | Can do anything inside the workspace. | + +**Notes:** + +* **Be careful:** Granting access to the **default** workspace gives access to all workspaces in the organization. + +* The **default** workspace only has three roles: *workspace-admin*, *workspace-super admin*, and *workspace-read-only*. Every other workspace will have the four roles mentioned above. + +* You can also create custom roles by clicking on the **Add Role** button and specifying the endpoints that the administrator with the role will be able to interact with. +{% endnavtab %} +{% navtab Using the Admin API %} +Create a new workspace called SecureWorkspace, substituting the `kong_admin` +account’s password in place of ``: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/workspaces \ + -H Kong-Admin-Token: \ + --data 'name=SecureWorkspace' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/workspaces \ + name=SecureWorkspace \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +**Note:** Each workspace name should be unique, regardless of letter case. For example, naming one workspace “Payments” and another one “payments” will create two different workspaces that appear identical. + +**WARNING:** +* Granting access to the **default** workspace gives access to all workspaces in the organization. +* Do not give a workspace the same name as any of these major routes in Kong Manager: + + |---------|-----------|--------------|---------------| + | Admins | APIs | Certificates | Consumers | + | Plugins | Portal | Routes | Services | + | SNIs | Upstreams | Vitals | PermalinkStep | + +If you are unable to log in with `kong_admin`'s token, and you know the credentials are correct, then something is likely wrong with your {{site.base_gateway}} configuration. Double-check the settings, or, if the cause of the problem still isn’t clear, work with your {{site.konnect_product_name}} account team and Kong support for assistance. + +{% endnavtab %} +{% endnavtabs %} + +## Create an Admin + +Next, create an admin for the SecureWorkspace, granting them permissions to manage only that workspace. + +{% navtabs %} +{% navtab Using Kong Manager %} +### Invite a New Admin + +{:.note} +> If you also use the Admin API, once you've created this admin, you can find it under the `/admins` endpoint. + +1. From the **Teams** > **Admins** tab, click **Invite Admin**. +2. Enter the new administrator’s **Email** address, **Username**, and **Custom Id**. +3. Ensure that **Enable RBAC Token** is enabled. + + **Note:** This setting lets the admin use the Admin API as well as Kong Manager. If you don’t want this user to access the Admin API, uncheck this box. + +4. Click **Add/Edit Roles**. +5. In the Workspace Access dialog, select the **SecureWorkspace**. +6. Select the **workspace-admin** role, which makes this user the workspace administrator for the SecureWorkspace. + + When you are done adding roles, you are redirected back to the Invite Admin dialog. + + {:.important} + **Important:** Before you move on, make sure the **Enable RBAC Token** checkbox is checked. The RBAC token is what allows the new admin to send a token to the Admin API to configure the system programmatically. + +7. Click **Invite Admin** to send the invite. + + At this point in the getting started guide, you likely haven’t set up SMTP yet, so no email will be sent. Instead, you’ll later generate a registration link for the new administrator manually. + +#### Register the Admin + +1. Back on the **Teams** page, click **View** for the administrator you just created. +2. Click the **Generate registration link** button. + + Using this link, the new administrator can go to a web browser and paste it in to initiate his/her account and create an initial password. Again, normally, this would happen through SMTP, and the user would get this link through an email. + +3. Click the **copy icon** to copy the registration link, then save it. +4. Email or SMS the registration link to the new administrator — or use it yourself to test the login in the following steps. +5. Open a different browser or an incognito tab in the current browser so your existing login session is ignored. +6. Enter the registration link you copied previously into the new browser to log in with the new administrator (`secureworkspaceadmin`). + + If the registration link has expired, you can generate a new one by logging in with your `kong_admin` administrator and generating a new link. + +7. Enter a new password for your new administrator (save this in a secure place) and click on the **Register** button. + + If everything went well, you should see an “Account Setup Success” message. +{% endnavtab %} +{% navtab Using the Admin API %} + +{:.important} +> **Note** The following method refers to the `/users` endpoint and creates an Admin API user that won't be visible (or manageable) through Kong Manager. If you want to later administer the admin through Kong Manager, create it under the [`/admins`](/gateway/{{page.release}}/admin-api/admins/reference/) endpoint instead. + +Create a new user named `secureworkspaceadmin` with the RBAC token +`secureadmintoken`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/SecureWorkspace/rbac/users \ + -H Kong-Admin-Token: \ + --data 'name=secureworkspaceadmin' \ + --data 'user_token=secureadmintoken' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/SecureWorkspace/rbac/users \ + name=secureworkspaceadmin \ + user_token=secureadmintoken \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +Create a blank role in the workspace and name it `admin`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/SecureWorkspace/rbac/roles \ + -H Kong-Admin-Token: \ + --data 'name=admin' \ +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/SecureWorkspace/rbac/roles/ \ + name=admin \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +Give the `admin` role permissions to do everything on all endpoints in the +workspace: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/SecureWorkspace/rbac/roles/admin/endpoints/ \ + -H Kong-Admin-Token: \ + --data 'endpoint=*' + --data 'workspace=SecureWorkspace' \ + --data 'actions=*' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/SecureWorkspace/rbac/roles/admin/endpoints/ \ + endpoint='*' \ + workspace=SecureWorkspace \ + actions='*' \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +Grant the `admin` role to `secureworkspaceadmin`: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/SecureWorkspace/rbac/users/secureworkspaceadmin/roles/ \ + -H Kong-Admin-Token: \ + --data 'role=admin' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/SecureWorkspace/rbac/users/secureworkspaceadmin/roles/ \ + roles=admin \ + Kong-Admin-Token: +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% endnavtabs %} + +## Verify the New Admin + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Click the **Login** button to be taken to a new screen to log in with your new administrator. +2. Enter the **Username** and **Password** of your new administrator and click **Login** again. + + Once you log in, you’ll notice that you can only see the SecureWorkspace. + +3. You can also verify that this user’s administration rights are limited. As this user, if you open the Teams tab and try to add new administrators, Admin API users (RBAC users), Groups, or Roles, you won’t have the permissions to do so. + +{% endnavtab %} +{% navtab Using the Admin API %} +1. Try to access the `default` workspace using `secureworkspaceadmin`'s user token. + + *Using cURL:* + ```sh + curl -H Kong-Admin-Token:secureadmintoken -X GET http://localhost:8001/default/rbac/users + ``` + *Or using HTTPie:* + + ```sh + http :8001/default/rbac/users Kong-Admin-Token:secureadmintoken + ``` + + You should get a `403 Forbidden` error message: + ``` + { + “message”: “secureworkspaceadmin, you do not have permissions to read this resource” + } + ``` +2. Then, try to access the same endpoint, but this time in the `SecureWorkspace`. + + *Using cURL:* + ```sh + curl -H Kong-Admin-Token:secureadmintoken -X GET http://localhost:8001/SecureWorkspace/rbac/users + ``` + *Or using HTTPie:* + + ```sh + http :8001/SecureWorkspace/rbac/users Kong-Admin-Token:secureadmintoken + ``` + This time, you should get a `200 OK` success message and a list of users. + +{% endnavtab %} +{% endnavtabs %} + +That's it! You are now controlling access to {{site.base_gateway}} administration with RBAC. + +## Reference: Using decK with RBAC and Workspaces + +### RBAC + +Once RBAC is enabled, you will have to pass the `kong-admin-token` in a header +any time you use decK: + +``` bash +deck sync --headers "kong-admin-token:mytoken" +``` +> **Note:** You should not use an RBAC token with Super Admin +privileges for decK. Always scope down to the exact permissions you need to +give decK. + +### Workspaces + +When you have multiple workspaces, decK creates a file for each one. Export +them as follows: + +``` bash +deck dump --all-workspaces +``` + +Or, to export the configuration for only one workspace: + +``` bash +deck dump --workspace SecureWorkspace +``` + +You can use these flags with any decK commands to update and export your +configuration. + +## Summary and next steps + +In this topic, you: + +* Enabled RBAC. +* Created a workspace named `SecureWorkspace`. +* Created an admin named `secureworkspaceadmin` and granted them permissions to manage to everything in the `SecureWorkspace`. + +Next, set up the [Dev Portal](/gateway/{{page.release}}/get-started/comprehensive/dev-portal/). diff --git a/app/gateway/2.7.x/get-started/comprehensive/prepare.md b/app/gateway/2.7.x/get-started/comprehensive/prepare.md new file mode 100644 index 000000000000..d156538fdef5 --- /dev/null +++ b/app/gateway/2.7.x/get-started/comprehensive/prepare.md @@ -0,0 +1,156 @@ +--- +title: Prepare to Administer Kong Gateway +--- + +Before getting started with using {{site.base_gateway}}, verify that it was +installed correctly, and that you’re ready to administer it. + +## Before you begin + +Before you start this section, make sure that: + +* {{site.base_gateway}} is installed and running. +* Kong Manager (if applicable) and Kong Admin API ports are listening on the +appropriate port/IP/DNS settings. +* If using declarative configuration to configure {{site.base_gateway}}, +[decK](/deck/latest/installation) is installed. + +In this guide, an instance of {{site.base_gateway}} is referenced via +``. Make sure to replace `` with the hostname +of your control plane instance. + +## Verify the {{site.base_gateway}} configuration +{% navtabs %} +{% navtab Using Kong Manager %} +As a {{site.base_gateway}} user, you can use Kong Manager for environment +administration. You’re going to use it later on in this guide, so first make +sure you can access Kong Manager. + +Open a web browser and navigate to `http://localhost:8002`. + +If {{site.base_gateway}} was installed correctly, it automatically logs you +in and presents the Kong Manager Overview page. +{% endnavtab %} +{% navtab Using the Admin API %} +Ensure that you can send requests to the gateway's Admin API using either cURL +or HTTPie. + +View the current configuration by issuing the following command in a terminal +window: + + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X GET http://localhost:8001 +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http localhost:8001 +``` +{% endnavtab %} +{% endnavtabs %} + + +The current configuration returns. +{% endnavtab %} + +{% navtab Using decK (YAML) %} + +1. Check that decK is connected to {{site.base_gateway}}: + + ``` bash + deck ping + ``` + + You should see a success message with the version that you're + connected to: + ``` + Successfully connected to Kong! + Kong version: 2.1.0 + ``` + +2. Ensure that you can pull configuration from {{site.base_gateway}} by issuing +the following command in a terminal window: + + ``` bash + deck dump + ``` + + This command creates a `kong.yaml` file with the gateway's entire current + configuration, in the directory where decK is installed. + + You can also use this command at any time (for example, after a `deck sync`) + to see the {{site.base_gateway}}'s most recent configuration. + + {:.important} + > **Be careful!** Any subsequent `deck dump` will + overwrite the existing `kong.yaml` file. Create backups as needed. + +3. Open the file in your preferred code editor. Since you haven't configured +anything yet, the file should only contain the decK version: + + ``` yaml + _format_version: "1.1" + ``` + + You will use this file to configure {{site.base_gateway}}. + +{% endnavtab %} +{% endnavtabs %} + +## (Optional) Verify Control Plane and Data Plane connection + +If you're running {{site.base_gateway}} in [hybrid mode](/gateway/{{page.release}}/plan-and-deploy/hybrid-mode/), +you need to perform all tasks in this guide from the control plane. You can check +that all of your configurations are being pushed from the control plane to your +data planes using the Cluster Status CLI. + +Run the following from a control plane: + + +{% navtabs codeblock %} +{% navtab cURL %} +```bash +curl -i -X GET http://localhost:8001/clustering/data-planes +``` +{% endnavtab %} +{% navtab HTTPie %} +```bash +http :8001/clustering/data-planes +``` +{% endnavtab %} +{% endnavtabs %} + +The output shows all of the connected data plane instances in the cluster: + +```json +{ + "data": [ + { + "config_hash": "a9a166c59873245db8f1a747ba9a80a7", + "hostname": "data-plane-2", + "id": "ed58ac85-dba6-4946-999d-e8b5071607d4", + "ip": "192.168.10.3", + "last_seen": 1580623199, + "status": "connected" + }, + { + "config_hash": "a9a166c59873245db8f1a747ba9a80a7", + "hostname": "data-plane-1", + "id": "ed58ac85-dba6-4946-999d-e8b5071607d4", + "ip": "192.168.10.4", + "last_seen": 1580623200, + "status": "connected" + } + ], + "next": null +} +``` + +## Summary and next steps + +In this section, you learned about the methods of administering +{{site.base_gateway}} and how to access its configuration. Next, go on to +learn about [exposing your services with {{site.base_gateway}}](/gateway/{{page.release}}/get-started/comprehensive/expose-services/). diff --git a/app/gateway/2.7.x/get-started/comprehensive/protect-services.md b/app/gateway/2.7.x/get-started/comprehensive/protect-services.md new file mode 100644 index 000000000000..dd5a896c3be7 --- /dev/null +++ b/app/gateway/2.7.x/get-started/comprehensive/protect-services.md @@ -0,0 +1,184 @@ +--- +title: Protect your Services +--- +In this topic, you’ll learn how to enforce rate limiting using the Rate Limiting plugin. + +If you are following the getting started workflow, make sure you have completed [Exposing Your Services](/gateway/{{page.release}}/get-started/comprehensive/expose-services/) before moving on. + +## What is Rate Limiting? + +Kong's [Rate Limiting plugin](/hub/kong-inc/rate-limiting/) lets you restrict how many requests your upstream services receive from your API consumers, or how often each user can call the API. + +{:.note} +> The [**Rate Limiting Advanced**](/hub/kong-inc/rate-limiting-advanced/) plugin provides support for the sliding window algorithm to prevent the API from being overloaded near the window boundaries, and adds Redis support for greater performance. + +## Why Use Rate Limiting? + +Rate limiting protects the APIs from accidental or malicious overuse. Without rate limiting, each user may request as often as they like, which can lead to spikes of requests that starve other consumers. After rate limiting is enabled, API calls are limited to a fixed number of requests per second. + +## Set up Rate Limiting + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Access your Kong Manager instance and your **default** workspace. + +2. Go to **API Gateway** > **Plugins**. + +3. Click **New Plugin**. + +4. Scroll down to **Traffic Control** and find the **Rate Limiting Advanced** plugin. Click **Enable**. + +5. Apply the plugin as **Global**, which means the rate limiting applies to all requests, including every Service and Route in the Workspace. + + If you switched it to **Scoped**, the rate limiting would apply the plugin to only one Service, Route, or Consumer. + + > **Note**: By default, the plugin is automatically enabled when the form is submitted. You can also toggle the **This plugin is Enabled** button at the top of the form to configure the plugin without enabling it. For this example, keep the plugin enabled. + +6. Scroll down and complete only the following fields with the following parameters. + 1. config.limit: `5` + 2. config.sync_rate: `-1` + 3. config.window_size: `30` + + Besides the above fields, there may be others populated with default values. For this example, leave the rest of the fields as they are. + +7. Click **Create**. +{% endnavtab %} +{% navtab Using the Admin API %} + +{:.note} +> **Note:** This section sets up the basic Rate Limiting plugin. If you have a {{site.base_gateway}} instance, see instructions for **Using Kong Manager** to set up Rate Limiting Advanced with sliding window support instead. + +Call the Admin API on port `8001` and configure plugins to enable a limit of five (5) requests per minute, stored locally and in-memory, on the node. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/plugins \ + --data name=rate-limiting \ + --data config.minute=5 \ + --data config.policy=local +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f post :8001/plugins \ + name=rate-limiting \ + config.minute=5 \ + config.policy=local +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +{:.note} +> **Note:** This section sets up the basic Rate Limiting plugin. If you have a {{site.base_gateway}} instance, see instructions for **Using Kong Manager** to set up Rate Limiting Advanced with sliding window support instead. + +1. Add a new `plugins` section to the bottom of your `kong.yaml` file. Enable +`rate-limiting` with a limit of five (5) requests per minute, stored locally +and in-memory, on the node: + + ``` yaml + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + ``` + + This plugin will be applied globally, which means the rate limiting + applies to all requests, including every Service and Route in the Workspace. + + If you pasted the plugin section under an existing Service, Route, or + Consumer, the rate limiting would only apply to that specific + entity. + + >**Note**: By default, `enabled` is set to `true` for the plugin. You can + disable the plugin at any time by setting `enabled: false`. + +2. Sync the configuration: + + ``` bash + deck sync + ``` + +{% endnavtab %} +{% endnavtabs %} + + +## Validate Rate Limiting + +{% navtabs %} +{% navtab Using a Web Browser %} + +1. Enter `:8000/mock` and refresh your browser six times. + After the 6th request, you’ll receive an error message. +2. Wait at least 30 seconds and try again. + The service will be accessible until the sixth (6th) access attempt within a 30-second window. + +{% endnavtab %} +{% navtab Using the Admin API %} + +To validate rate limiting, access the API six (6) times from the CLI to confirm the requests are rate limited. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X GET http://localhost:8000/mock/anything +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock/anything +``` +{% endnavtab %} +{% endnavtabs %} + + + +After the 6th request, you should receive a 429 "API rate limit exceeded" error: +``` +{ +"message": "API rate limit exceeded" +} +``` +{% endnavtab %} +{% endnavtabs %} + + +## Summary and next steps + +In this section: + +* If using the Admin API or decK, you enabled the Rate Limiting plugin, +setting the rate limit to 5 times per minute. +* If using Kong Manager, you enabled the Rate Limiting Advanced plugin, +setting the rate limit to 5 times for every 30 seconds. + +Next, head on to learn about [proxy caching](/gateway/{{page.release}}/get-started/comprehensive/improve-performance/). diff --git a/app/gateway/2.7.x/get-started/comprehensive/secure-services.md b/app/gateway/2.7.x/get-started/comprehensive/secure-services.md new file mode 100644 index 000000000000..b9ed3ec1b564 --- /dev/null +++ b/app/gateway/2.7.x/get-started/comprehensive/secure-services.md @@ -0,0 +1,417 @@ +--- +title: Secure your Services Using Authentication +--- +In this topic, you’ll learn about API Gateway authentication, set up the Key Authentication plugin, and add a consumer. + +If you are following the getting started workflow, make sure you have completed [Improve Performance with Proxy Caching](/gateway/{{page.release}}/get-started/comprehensive/improve-performance/) before moving on. + +## What is Authentication? + +API gateway authentication is an important way to control the data that is allowed to be transmitted using your APIs. Basically, it checks that a particular consumer has permission to access the API, using a predefined set of credentials. + +{{site.base_gateway}} has a library of plugins that provide simple ways to implement the best known and most widely used [methods of API gateway authentication](/hub/#authentication). Here are some of the commonly used ones: + +* Basic Authentication +* Key Authentication +* OAuth 2.0 Authentication +* LDAP Authentication Advanced +* OpenID Connect + +Authentication plugins can be configured to apply to service entities within the {{site.base_gateway}}. In turn, service entities are mapped one-to-one with the upstream services they represent, essentially meaning that the authentication plugins apply directly to those upstream services. + +## Why use API Gateway Authentication? + +With authentication turned on, {{site.base_gateway}} won’t proxy requests unless the client successfully authenticates first. This means that the upstream (API) doesn’t need to authenticate client requests, and it doesn’t waste critical resources validating credentials. + +{{site.base_gateway}} has visibility into all authentication attempts, successful, failed, and so on, which provides the ability to catalog and dashboard those events to prove the right controls are in place, and to achieve compliance. Authentication also gives you an opportunity to determine how a failed request is handled. This might mean simply blocking the request and returning an error code, or in some circumstances, you might still want to provide limited access. + +In this example, you’re going to enable the **Key Authentication plugin**. API key authentication is one of the most popular ways to conduct API authentication and can be implemented to create and delete access keys as required. + +For more information, see [What is API Gateway Authentication?](https://konghq.com/learning-center/api-gateway/api-gateway-authentication). + +## Set up the Key Authentication Plugin + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. Access your Kong Manager instance and your **default** workspace. +2. Go to the **Routes** page and select the **mocking** route you created. +3. Click **View**. +4. On the Scroll down and select the **Plugins** tab, then click **Add a Plugin**. +5. In the Authentication section, find the **Key Authentication** plugin and click **Enable**. +6. In the **Create new key-auth plugin** dialog, the plugin fields are automatically scoped to the route because the plugin is selected from the mocking Routes page. + + For this example, this means that you can use all of the default values. + +7. Click **Create**. + + Once the plugin is enabled on the route, **key-auth** displays under the Plugins section on the route’s overview page. + +Now, if you try to access the route without providing an API key, the request will fail, and you’ll see the message `"No API key found in request".` + +Before Kong proxies requests for this route, it needs an API key. For this example, since you installed the Key Authentication plugin, you need to create a consumer with an associated key first. +{% endnavtab %} +{% navtab Using the Admin API %} + +Call the Admin API on port `8001` and configure plugins to enable key +authentication. For this example, apply the plugin to the */mock* route you +created: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X POST http://localhost:8001/routes/mocking/plugins \ + --data name=key-auth +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/routes/mocking/plugins \ + name=key-auth +``` +{% endnavtab %} +{% endnavtabs %} + + +Try to access the service again: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i http://localhost:8000/mock +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock +``` +{% endnavtab %} +{% endnavtabs %} + + +Since you added key authentication, you should be unable to access it: + +```sh +HTTP/1.1 401 Unauthorized +... +{ + "message": "No API key found in request" +} +``` + +Before Kong proxies requests for this route, it needs an API key. For this +example, since you installed the Key Authentication plugin, you need to create +a consumer with an associated key first. + +{% endnavtab %} +{% navtab Using decK (YAML) %} +1. Under the `mocking` route in the `routes` section of the `kong.yaml` file, +add a plugin section and enable the `key-auth` plugin: + + ``` yaml + plugins: + - name: key-auth + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: key-auth + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + +2. Sync the configuration: + + ``` bash + deck sync + ``` + +Now, if you try to access the route at `http://localhost:8000/mock` +without providing an API key, the request will fail, and you’ll see the message +`"No API key found in request".` + +Before Kong proxies requests for this route, it needs an API key. For this +example, since you installed the Key Authentication plugin, you need to create +a consumer with an associated key first. + +{% endnavtab %} +{% endnavtabs %} + + +## Set up Consumers and Credentials + +{% navtabs %} +{% navtab Using Kong Manager %} + +1. In Kong Manager, go to **API Gateway** > **Consumers**. +2. Click **New Consumer**. +3. Enter the **Username** and **Custom ID**. For this example, use `consumer` for each field. +4. Click **Create**. +5. On the Consumers page, find your new consumer and click **View**. +6. Scroll down the page and click the **Credentials** tab. +7. Click **New Key Auth Credential**. +8. Set the key to `apikey` and click **Create**. + + The new Key Authentication ID displays on the **Consumers** page under the **Credentials** tab. +{% endnavtab %} +{% navtab Using the Admin API %} + +To create a consumer, call the Admin API and the consumer’s endpoint. +The following creates a new consumer called **consumer**: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers/ \ + --data username=consumer \ + --data custom_id=consumer +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/consumers \ + username=consumer \ + custom_id=consumer +``` +{% endnavtab %} +{% endnavtabs %} + + +Once provisioned, call the Admin API to provision a key for the consumer +created above. For this example, set the key to `apikey`. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i -X POST http://localhost:8001/consumers/consumer/key-auth \ + --data key=apikey +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/consumers/consumer/key-auth \ + key=apikey +``` +{% endnavtab %} +{% endnavtabs %} + + +If no key is entered, Kong automatically generates the key. + +Result: + +```sh +HTTP/1.1 201 Created +... +{ + "consumer": { + "id": "2c43c08b-ba6d-444a-8687-3394bb215350" + }, + "created_at": 1568255693, + "id": "86d283dd-27ee-473c-9a1d-a567c6a76d8e", + "key": "apikey" +} +``` + +You now have a consumer with an API key provisioned to access the route. + +{% endnavtab %} +{% navtab Using decK (YAML) %} +1. Add a `consumers` section to your `kong.yaml` file and create a new consumer: + + ``` yaml + consumers: + - custom_id: consumer + username: consumer + keyauth_credentials: + - key: apikey + ``` + + Your file should now look like this: + + ``` yaml + _format_version: "1.1" + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: mocking + paths: + - /mock + strip_path: true + plugins: + - name: key-auth + consumers: + - custom_id: consumer + username: consumer + keyauth_credentials: + - key: apikey + plugins: + - name: rate-limiting + config: + minute: 5 + policy: local + - name: proxy-cache + config: + content_type: + - "application/json; charset=utf-8" + cache_ttl: 30 + strategy: memory + ``` + +2. Sync the configuration: + + ``` bash + deck sync + ``` + +You now have a consumer with an API key provisioned to access the route. + +{% endnavtab %} +{% endnavtabs %} + + +## Validate Key Authentication + +{% navtabs %} +{% navtab Using a Web Browser %} + +To validate the Key Authentication plugin, access your route through your browser by appending `?apikey=apikey` to the url: +``` +http://localhost:8000/mock?apikey=apikey +``` + +{% endnavtab %} +{% navtab Using the Admin API %} +To validate the Key Authentication plugin, access the *mocking* route again, using the header `apikey` with a key value of `apikey`. + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -i http://localhost:8000/mock/anything \ + -H 'apikey:apikey' +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8000/mock/anything apikey:apikey +``` +{% endnavtab %} +{% endnavtabs %} + + +You should get an `HTTP/1.1 200 OK` message in response. + +{% endnavtab %} +{% endnavtabs %} + +## (Optional) Disable the plugin +If you are following this getting started guide topic by topic, you will need to use this API key in any requests going forward. If you don’t want to keep specifying the key, disable the plugin before moving on. + +{% navtabs %} +{% navtab Using Kong Manager %} +1. Go to the Plugins page and click on **View** for the key-auth row. +2. Use the toggle at the top of the page to switch the plugin from **Enabled** to **Disabled**. +{% endnavtab %} +{% navtab Using the Admin API %} + +Find the plugin ID and copy it: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X GET http://localhost:8001/routes/mocking/plugins/ +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http :8001/routes/mocking/plugins +``` +{% endnavtab %} +{% endnavtabs %} + + +Output: +```sh +"id": "2512e48d9-7by0-674c-84b7-00606792f96b" +``` + +Disable the plugin: + + +{% navtabs codeblock %} +{% navtab cURL %} +```sh +curl -X PATCH http://localhost:8001/routes/mocking/plugins/{} \ + --data enabled=false +``` +{% endnavtab %} +{% navtab HTTPie %} +```sh +http -f patch :8001/routes/mocking/plugins/{} \ + enabled=false +``` +{% endnavtab %} +{% endnavtabs %} + + +{% endnavtab %} +{% navtab Using decK (YAML) %} + +1. Disable the key-auth plugin in the `kong.yaml` file by setting +`enabled` to `false`: + + ``` yaml + plugins: + - name: key-auth + enabled: false + ``` + +2. Sync the configuration: + + ``` bash + $ deck sync + ``` + +{% endnavtab %} +{% endnavtabs %} + +## Summary and next steps + +In this topic, you: + +* Enabled the Key Authentication plugin. +* Created a new consumer named `consumer`. +* Gave the consumer an API key of `apikey` so that it could access the `/mock` route with authentication. + +Next, you’ll learn about [load balancing upstream services using targets](/gateway/{{page.release}}/get-started/comprehensive/load-balancing/). diff --git a/app/gateway/2.7.x/get-started/quickstart/adding-consumers.md b/app/gateway/2.7.x/get-started/quickstart/adding-consumers.md new file mode 100644 index 000000000000..6f0809b1c3f0 --- /dev/null +++ b/app/gateway/2.7.x/get-started/quickstart/adding-consumers.md @@ -0,0 +1,90 @@ +--- +title: Adding Consumers +--- + +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. + +## Before you start + +* You have installed and started {{site.base_gateway}}, either through the [Docker quickstart](/gateway/{{page.release}}/get-started/quickstart/) or a more [comprehensive installation](/gateway/{{page.release}}/install-and-run/). +* You have [configured a Service](/gateway/{{page.release}}/get-started/quickstart/configuring-a-service/) +* You have [enabled the key-auth plugin](/gateway/{{page.release}}/get-started/quickstart/enabling-plugins/) + +## 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](https://konghq.com/community/) +for help! + +[key-auth]: /hub/kong-inc/key-auth +[API-consumers]: /gateway/{{page.release}}/admin-api#create-consumer +[enabling-plugins]: /gateway/{{page.release}}/get-started/quickstart/enabling-plugins +[configuration]: /gateway/{{page.release}}/reference/configuration +[CLI]: /gateway/{{page.release}}/reference/cli +[proxy]: /gateway/{{page.release}}/reference/proxy +[API]: /gateway/{{page.release}}/admin-api +[cluster]: /gateway/{{page.release}}/reference/clustering diff --git a/app/gateway/2.7.x/get-started/quickstart/configuring-a-grpc-service.md b/app/gateway/2.7.x/get-started/quickstart/configuring-a-grpc-service.md new file mode 100644 index 000000000000..0e3f98ccfded --- /dev/null +++ b/app/gateway/2.7.x/get-started/quickstart/configuring-a-grpc-service.md @@ -0,0 +1,284 @@ +--- +title: Configuring a gRPC Service +--- + +Note: this guide assumes familiarity with gRPC; for learning how to set up +Kong with an upstream REST API, check out the [Configuring a Service guide][conf-service]. + +Starting with version 1.3, gRPC proxying is natively supported in Kong. In this +section, you'll learn how to configure Kong to manage your gRPC services. For the +purpose of this guide, we'll use [grpcurl][grpcurl] and [grpcbin][grpcbin] - they +provide a gRPC client and gRPC services, respectively. + +We will describe two setups: Single gRPC Service and Route and single gRPC Service +with multiple Routes. In the former, a single catch-all Route is configured, which +proxies all matching gRPC traffic to an upstream gRPC service; the latter demonstrates +how to use a Route per gRPC method. + +In Kong 1.3, gRPC support assumes gRPC over HTTP/2 framing. As such, make sure +you have at least one HTTP/2 proxy listener (check out the [Configuration Reference][configuration-reference] +for how to). In this guide, we will assume Kong is listening for HTTP/2 proxy +requests on port 9080. + +## Before you start + +You have installed and started {{site.base_gateway}}, either through the [Docker quickstart](/gateway/{{page.release}}/get-started/quickstart/) or a more [comprehensive installation](/gateway/{{page.release}}/install-and-run/). + +## 1. Single gRPC Service and Route + +Issue the following request to create a gRPC Service (assuming your gRPC +server is listening in localhost, port 15002): + +```bash +curl -XPOST localhost:8001/services \ + --data name=grpc \ + --data protocol=grpc \ + --data host=localhost \ + --data port=15002 +``` + +Issue the following request to create a gRPC route: + +```bash +curl -XPOST localhost:8001/services/grpc/routes \ + --data protocols=grpc \ + --data name=catch-all \ + --data paths=/ +``` + +Using the [grpcurl][grpcurl] command line client, issue the following gRPC +request: + +```bash +grpcurl -v -d '{"greeting": "Kong 1.3!"}' \ + -plaintext localhost:9080 hello.HelloService.SayHello +``` + +The response should resemble the following: + +``` +Resolved method descriptor: +rpc SayHello ( .hello.HelloRequest ) returns ( .hello.HelloResponse ); + +Request metadata to send: +(empty) + +Response headers received: +content-type: application/grpc +date: Tue, 16 Jul 2019 21:37:36 GMT +server: openresty/1.15.8.1 +via: kong/1.2.1 +x-kong-proxy-latency: 0 +x-kong-upstream-latency: 0 + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response trailers received: +(empty) +Sent 1 request and received 1 response +``` + +Notice that Kong response headers, such as `via` and `x-kong-proxy-latency`, were +inserted in the response. + +## 2. Single gRPC Service with Multiple Routes + +Building on top of the previous example, let's create a few more routes, for +individual gRPC methods. + +The gRPC "HelloService" service being used in this example exposes a few different +methods, as can be seen in [its protobuf file][protobuf]. We will create individual +routes for its "SayHello" and LotsOfReplies methods. + +Create a Route for "SayHello": + +```bash +curl -X POST localhost:8001/services/grpc/routes \ + --data protocols=grpc \ + --data paths=/hello.HelloService/SayHello \ + --data name=say-hello +``` + +Create a Route for "LotsOfReplies": + +```bash +curl -X POST localhost:8001/services/grpc/routes \ + --data protocols=grpc \ + --data paths=/hello.HelloService/LotsOfReplies \ + --data name=lots-of-replies +``` + +With this setup, gRPC requests to the "SayHello" method will match the first +Route, while requests to "LotsOfReplies" will be routed to the latter. + +Issue a gRPC request to the "SayHello" method: + +```bash +grpcurl -v -d '{"greeting": "Kong 1.3!"}' \ + -H 'kong-debug: 1' -plaintext \ + localhost:9080 hello.HelloService.SayHello +``` + +(Notice we are sending a header `kong-debug`, which causes Kong to insert +debugging information in response headers.) + +The response should look like: + +``` +Resolved method descriptor: +rpc SayHello ( .hello.HelloRequest ) returns ( .hello.HelloResponse ); + +Request metadata to send: +kong-debug: 1 + +Response headers received: +content-type: application/grpc +date: Tue, 16 Jul 2019 21:57:00 GMT +kong-route-id: 390ef3d1-d092-4401-99ca-0b4e42453d97 +kong-service-id: d82736b7-a4fd-4530-b575-c68d94c3493a +kong-service-name: s1 +server: openresty/1.15.8.1 +via: kong/1.2.1 +x-kong-proxy-latency: 0 +x-kong-upstream-latency: 0 + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response trailers received: +(empty) +Sent 1 request and received 1 response +``` + +Notice the Route ID should refer to the first route we created. + +Similarly, let's issue a request to the "LotsOfReplies" gRPC method: + +```bash +grpcurl -v -d '{"greeting": "Kong 1.3!"}' \ + -H 'kong-debug: 1' -plaintext \ + localhost:9080 hello.HelloService.LotsOfReplies +``` + +The response should look like the following: + +``` +Resolved method descriptor: +rpc LotsOfReplies ( .hello.HelloRequest ) returns ( stream .hello.HelloResponse ); + +Request metadata to send: +kong-debug: 1 + +Response headers received: +content-type: application/grpc +date: Tue, 30 Jul 2019 22:21:40 GMT +kong-route-id: 133659bb-7e88-4ac5-b177-bc04b3974c87 +kong-service-id: 31a87674-f984-4f75-8abc-85da478e204f +kong-service-name: grpc +server: openresty/1.15.8.1 +via: kong/1.2.1 +x-kong-proxy-latency: 14 +x-kong-upstream-latency: 0 + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response contents: +{ + "reply": "hello Kong 1.3!" +} + +Response trailers received: +(empty) +Sent 1 request and received 10 responses +``` + +Notice that the `kong-route-id` response header now carries a different value +and refers to the second Route created in this page. + +**Note:** +Some gRPC clients (typically CLI clients) issue ["gRPC Reflection Requests"][grpc-reflection] +as a means of determining what methods a server exports and how those methods are called. +Said requests have a particular path; for example, `/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo` +is a valid reflection path. As with any proxy request, Kong needs to know how to +route these; in the current example, they would be routed to the catch-all route +(whose path is `/`, matching any path). If no route matches the gRPC reflection +request, Kong will respond, as expected, with a `404 Not Found` response. + +## 3. Enabling Plugins + +Kong 1.3 gRPC support is compatible with Logging and Observability plugins; for +example, let's try out the [File Log][file-log] plugin with gRPC. + +Issue the following request to enable File Log on the "SayHello" route: + +```bash +curl -X POST localhost:8001/routes/say-hello/plugins \ + --data name=file-log \ + --data config.path=grpc-say-hello.log +``` + +Follow the output of the log as gRPC requests are made to "SayHello": + +``` +tail -f grpc-say-hello.log +{"latencies":{"request":8,"kong":5,"proxy":3},"service":{"host":"localhost","created_at":1564527408,"connect_timeout":60000,"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","protocol":"grpc","name":"grpc","read_timeout":60000,"port":15002,"updated_at":1564527408,"write_timeout":60000,"retries":5},"request":{"querystring":{},"size":"46","uri":"\/hello.HelloService\/SayHello","url":"http:\/\/localhost:9080\/hello.HelloService\/SayHello","headers":{"host":"localhost:9080","content-type":"application\/grpc","kong-debug":"1","user-agent":"grpc-go\/1.20.0-dev","te":"trailers"},"method":"POST"},"client_ip":"127.0.0.1","tries":[{"balancer_latency":0,"port":15002,"balancer_start":1564527732522,"ip":"127.0.0.1"}],"response":{"headers":{"kong-route-id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","content-type":"application\/grpc","connection":"close","kong-service-name":"grpc","kong-service-id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","kong-route-name":"say-hello","via":"kong\/1.2.1","x-kong-proxy-latency":"5","x-kong-upstream-latency":"3"},"status":200,"size":"298"},"route":{"id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","updated_at":1564527431,"protocols":["grpc"],"created_at":1564527431,"service":{"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c"},"name":"say-hello","preserve_host":false,"regex_priority":0,"strip_path":false,"paths":["\/hello.HelloService\/SayHello"],"https_redirect_status_code":426},"started_at":1564527732516} +{"latencies":{"request":3,"kong":1,"proxy":1},"service":{"host":"localhost","created_at":1564527408,"connect_timeout":60000,"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","protocol":"grpc","name":"grpc","read_timeout":60000,"port":15002,"updated_at":1564527408,"write_timeout":60000,"retries":5},"request":{"querystring":{},"size":"46","uri":"\/hello.HelloService\/SayHello","url":"http:\/\/localhost:9080\/hello.HelloService\/SayHello","headers":{"host":"localhost:9080","content-type":"application\/grpc","kong-debug":"1","user-agent":"grpc-go\/1.20.0-dev","te":"trailers"},"method":"POST"},"client_ip":"127.0.0.1","tries":[{"balancer_latency":0,"port":15002,"balancer_start":1564527733555,"ip":"127.0.0.1"}],"response":{"headers":{"kong-route-id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","content-type":"application\/grpc","connection":"close","kong-service-name":"grpc","kong-service-id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c","kong-route-name":"say-hello","via":"kong\/1.2.1","x-kong-proxy-latency":"1","x-kong-upstream-latency":"1"},"status":200,"size":"298"},"route":{"id":"e49f2df9-3e8e-4bdb-8ce6-2c505eac4ab6","updated_at":1564527431,"protocols":["grpc"],"created_at":1564527431,"service":{"id":"74a95d95-fbe4-4ddb-a448-b8faf07ece4c"},"name":"say-hello","preserve_host":false,"regex_priority":0,"strip_path":false,"paths":["\/hello.HelloService\/SayHello"],"https_redirect_status_code":426},"started_at":1564527733554} +``` + +[enabling-plugins]: /gateway/{{page.release}}/get-started/quickstart/enabling-plugins +[conf-service]: /gateway/{{page.release}}/get-started/quickstart/configuring-a-service +[configuration-reference]: /gateway/{{page.release}}/reference/configuration/ +[grpc-reflection]: https://github.com/grpc/grpc/blob/master/doc/server_reflection_tutorial.md +[grpcbin]: https://github.com/moul/grpcbin +[grpcurl]: https://github.com/fullstorydev/grpcurl +[protobuf]: https://raw.githubusercontent.com/moul/pb/master/hello/hello.proto +[file-log]: /hub/kong-inc/file-log +[zipkin]: /hub/kong-inc/zipkin diff --git a/app/gateway/2.7.x/get-started/quickstart/configuring-a-service.md b/app/gateway/2.7.x/get-started/quickstart/configuring-a-service.md new file mode 100644 index 000000000000..a77e174f5225 --- /dev/null +++ b/app/gateway/2.7.x/get-started/quickstart/configuring-a-service.md @@ -0,0 +1,132 @@ +--- +title: Configuring a Service +--- + +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 [httpbin API][httpbin]. Httpbin 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. + +## Before you start +You have installed and started {{site.base_gateway}}, either through the [Docker quickstart](/gateway/{{page.release}}/get-started/quickstart/) or a more [comprehensive installation](/gateway/{{page.release}}/install-and-run/). + +## 1. Add your Service using the Admin API + +Issue the following cURL request to add your first Service (pointing to the [httpbin API][httpbin]) +to Kong: + +```bash +curl -i -X POST \ + --url http://localhost:8001/services/ \ + --data 'name=example-service' \ + --data 'url=https://httpbin.konghq.com' +``` + +You should receive a response similar to: + +```http +HTTP/1.1 201 Created +Content-Type: application/json +Connection: keep-alive + +{ + "host":"httpbin.konghq.com", + "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]: /gateway/{{page.release}}/admin-api +[enabling-plugins]: /gateway/{{page.release}}/get-started/quickstart/enabling-plugins +[proxy-port]: /gateway/{{page.release}}/reference/configuration/#nginx-section +[httpbin]: https://httpbin.konghq.com/ diff --git a/app/gateway/2.7.x/get-started/quickstart/enabling-plugins.md b/app/gateway/2.7.x/get-started/quickstart/enabling-plugins.md new file mode 100644 index 000000000000..dfe5ced0ed91 --- /dev/null +++ b/app/gateway/2.7.x/get-started/quickstart/enabling-plugins.md @@ -0,0 +1,69 @@ +--- +title: Enabling Plugins +--- + +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. + +## Before you start + +* You have installed and started {{site.base_gateway}}, either through the [Docker quickstart](/gateway/{{page.release}}/get-started/quickstart/) or a more [comprehensive installation](/gateway/{{page.release}}/install-and-run/) +* You have [configured your Service](/gateway/{{page.release}}/get-started/quickstart/configuring-a-service/) in {{site.base_gateway}} + +## 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 API key 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]: /hub/kong-inc/key-auth +[plugins]: /hub/ +[adding-consumers]: /gateway/{{page.release}}/get-started/quickstart/adding-consumers diff --git a/app/gateway/2.7.x/get-started/quickstart/index.md b/app/gateway/2.7.x/get-started/quickstart/index.md new file mode 100644 index 000000000000..116c1c4ddcf8 --- /dev/null +++ b/app/gateway/2.7.x/get-started/quickstart/index.md @@ -0,0 +1,121 @@ +--- +title: Start Kong Gateway +--- + +In this section, you'll learn how to install and manage your {{site.base_gateway}} instance. First, you'll start {{site.base_gateway}} to gain access to its Admin +API, where you'll manage entities including Services, Routes, and Consumers. + +## Start {{site.base_gateway}} using Docker with a database + +One quick way to get {{site.base_gateway}} up and running is by using [Docker with a PostgreSQL database](/gateway/{{page.release}}/install-and-run/docker/). We recommend this method to test out basic {{site.base_gateway}} functionality. + +For a comprehensive list of installation options, see our [Install page](/gateway/{{page.release}}/install-and-run/). + +1. Create a Docker network: + + ```bash + docker network create kong-net + ``` + +2. Run a PostGreSQL container: + + ```bash + docker run -d --name kong-database \ + --network=kong-net \ + -p 5432:5432 \ + -e "POSTGRES_USER=kong" \ + -e "POSTGRES_DB=kong" \ + -e "POSTGRES_PASSWORD=kong" \ + postgres:9.6 + ``` + + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + + + Data sent through the Admin API is stored in Kong's [datastore][datastore-section] (Kong + supports PostgreSQL and Cassandra). + +3. Prep your database: + + ```bash + docker run --rm \ + --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_USER=kong" \ + -e "KONG_PG_PASSWORD=kong" \ + -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ + kong:latest kong migrations bootstrap + ``` + +4. Start Kong: + + ```bash + docker run -d --name kong \ + --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_USER=kong" \ + -e "KONG_PG_PASSWORD=kong" \ + -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 127.0.0.1:8001:8001 \ + -p 127.0.0.1:8444:8444 \ + kong:latest + ``` + +5. Navigate to `http://localhost:8001/`. + +## Kong default ports + +By default, Kong listens on the following ports: + +- `8000`: listens for incoming `HTTP` traffic from your + clients, and forwards it to your upstream services. +- `8001`: [Admin API][API] listens for calls from the command line over `HTTP`. +- `8443`: listens for incoming HTTPS traffic. This port has a + similar behavior to `8000`, except that it expects `HTTPS` + traffic only. This port can be disabled via the configuration file. +- `8444`: [Admin API][API] listens for `HTTPS` traffic. + +## Lifecycle commands + +{:.note} +> **Note**: If you are using Docker, [`exec`](https://docs.docker.com/engine/reference/commandline/exec) into the Docker container to use these commands. + +Stop {{site.base_gateway}} using the [stop][CLI] command: + +```bash +kong stop +``` + +Reload {{site.base_gateway}} using the [reload][CLI] command: + +```bash +kong reload +``` + +Start {{site.base_gateway}} using the [start][CLI] command: + +```bash +kong start +``` + +## Next Steps + +Now that you have {{site.base_gateway}} running, you can interact with the Admin API. + +To begin, go to [Configuring a Service ›][configuring-a-service] + +[configuration-loading]: /gateway/{{page.release}}/reference/configuration/#configuration-loading +[CLI]: /gateway/{{page.release}}/reference/cli +[API]: /gateway/{{page.release}}/admin-api +[datastore-section]: /gateway/{{page.release}}/reference/configuration/#datastore-section +[configuring-a-service]: /gateway/{{page.release}}/get-started/quickstart/configuring-a-service diff --git a/app/gateway/2.7.x/index.md b/app/gateway/2.7.x/index.md new file mode 100644 index 000000000000..127f685f10ec --- /dev/null +++ b/app/gateway/2.7.x/index.md @@ -0,0 +1,170 @@ +--- +title: Kong Gateway +subtitle: API gateway built for hybrid and multi-cloud, optimized for microservices and distributed architectures +--- + +{{site.base_gateway}} is a lightweight, fast, and flexible cloud-native API +gateway. An API gateway is a reverse proxy that lets you manage, configure, and route +requests to your APIs. + +{{site.base_gateway}} runs in front of any RESTful API and can be extended through +modules and plugins. It's designed to run on decentralized architectures, including +hybrid-cloud and multi-cloud deployments. + +With {{site.base_gateway}}, users can: + +* Leverage workflow automation and modern GitOps practices +* Decentralize applications/services and transition to microservices +* Create a thriving API developer ecosystem +* Proactively identify API-related anomalies and threats +* Secure and govern APIs/services, and improve API visibility across the +entire organization + +## Extending the {{site.base_gateway}} + +{{site.base_gateway}} is a Lua application running in Nginx. {{site.base_gateway}} +is distributed along with [OpenResty](https://openresty.org/), which is a bundle +of modules that extend the [lua-nginx-module](https://github.com/openresty/lua-nginx-module). + +This sets the foundations for a modular architecture, where +plugins can be enabled and executed at runtime. At its core, +{{site.base_gateway}} implements database abstraction, routing, and plugin +management. Plugins can live in separate code bases and be injected anywhere +into the request lifecycle, all with a few lines of code. + +Kong provides many [plugins](#kong-gateway-plugins) for you to use in your +Gateway deployments. You can also create your own custom plugins. For more +information, see the +[plugin development guide](/gateway/{{page.release}}/plugin-development), +the [PDK reference](/gateway/{{page.release}}/pdk/), and the guide on +[creating plugins with other languages](/gateway/{{page.release}}/reference/external-plugins). + +## Packages and modes + +{{site.base_gateway}} is available in the following modes: + +**{{site.base_gateway}} (OSS)**: an open-source package containing the basic API gateway +functionality and open-source plugins. You can manage the open-source Gateway +with Kong's [Admin API](#kong-admin-api) or with [declarative configuration](#deck). + +**{{site.base_gateway}}** (available in +[Free, Plus, or Enterprise modes](https://konghq.com/pricing)): Kong's API gateway +with added functionality. +* In **Free mode** , + this package adds [Kong Manager](#kong-manager) to the basic open-source functionality. +* In **Plus mode** , you have access to more +{{site.base_gateway}} features, but only through {{site.konnect_saas}}. +See the [{{site.konnect_saas}} documentation](/konnect/) and the +**Plus**-labelled plugins on the [Plugin Hub](/hub/) for more information. +* With an **Enterprise** subscription , + it also includes: + * [Dev Portal](#kong-dev-portal) + * [Vitals](#kong-vitals) + * [RBAC](/gateway/{{page.release}}/admin-api/rbac/reference/) + * [Enterprise plugins](/hub/) + +You can manage {{site.base_gateway}} in Free or Enterprise mode with Kong's +[Admin API](#kong-admin-api), [declarative configuration](#deck), or [Kong Manager](#kong-manager). + +This package is also available as part of +[{{site.konnect_product_name}}](/konnect/). + +![Introduction to {{site.base_gateway}}](/assets/images/products/gateway/gateway_overview.png) +> _Figure 1: Diagram of {{site.base_gateway}} modules and how they relate to the +foundational Gateway components._ +>
    +> _Requests flow from an API client into the +Gateway, are modified and managed by the proxy based on your Gateway +configuration, and forwarded to upstream services._ + +## Features + +### Kong Admin API + +[Kong Admin API](/gateway/{{page.release}}/admin-api) provides a RESTful +interface for administration and configuration of Services, Routes, Plugins, and +Consumers. All of the tasks you can perform against the Gateway can be automated +using the Kong Admin API. + +### Kong Manager +{:.badge .free} + +[Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager) is +the graphical user interface (GUI) for {{site.base_gateway}}. It uses the Kong +Admin API under the hood to administer and control {{site.base_gateway}}. + +Here are some of the things you can do with Kong Manager: + +* Create new Routes and Services +* Activate or deactivate plugins with a couple of clicks +* Group your teams, services, plugins, consumer management, and everything else +exactly how you want them +* Monitor performance: visualize cluster-wide, workspace-level, or +object-level health using intuitive, customizable dashboards + +### Kong Dev Portal +{:.badge .enterprise} + +[Kong Dev Portal](/gateway/{{page.release}}/developer-portal) is used to onboard new developers and to generate API documentation, create custom pages, manage API versions, and secure developer access. + +### Kong Vitals +{:.badge .enterprise} + +[Kong Vitals](/gateway/{{page.release}}/vitals) provides useful metrics about the health and performance of your {{site.base_gateway}} nodes, as well as metrics about the usage of your proxied APIs. You can visually monitor vital signs and pinpoint anomalies in real-time, and use visual API analytics to see exactly how your APIs and Gateway are performing and access key statistics. Kong Vitals is part of the Kong Manager UI. + +### Kubernetes + +{{site.base_gateway}} can run natively on Kubernetes with its custom [ingress controller](/kubernetes-ingress-controller/), Helm chart, and Operator. A Kubernetes ingress controller is a proxy that exposes Kubernetes services from applications (for example, Deployments, ReplicaSets) running on a Kubernetes cluster to client applications running outside of the cluster. The intent of an ingress controller is to provide a single point of control for all incoming traffic into the Kubernetes cluster. + +### {{site.base_gateway}} plugins + +[{{site.base_gateway}} plugins](/hub/) provide advanced functionality to better manage your API and microservices. With turnkey capabilities to meet the most challenging use cases, {{site.base_gateway}} plugins ensure maximum control and minimizes unnecessary overhead. Enable features like authentication, rate-limiting, and transformations by enabling {{site.base_gateway}} plugins through Kong Manager or the Admin API. + +## Tools +Kong also provides API lifecycle management tools that you can use with {{site.base_gateway}}. + +### Insomnia + +[Insomnia](https://docs.insomnia.rest) enables spec-first development for all REST and GraphQL services. With Insomnia, organizations can accelerate design and test workflows using automated testing, direct Git sync, and inspection of all response types. Teams of all sizes can use Insomnia to increase development velocity, reduce deployment risk, and increase collaboration. + +### decK +[decK](/deck) helps manage {{site.base_gateway}}’s configuration in a declarative fashion. +This means that a developer can define the desired state of {{site.base_gateway}} or +{{site.konnect_short_name}} – services, routes, plugins, and more – and let decK handle +implementation without needing to execute each step manually, as you would with +the Kong Admin API. + + +## Get started with {{site.base_gateway}} + +[Download and install {{site.base_gateway}}](/gateway/{{page.release}}/install-and-run). +To test it out, you can choose either the open-source package, or +run {{site.base_gateway}} in free mode and also try out Kong Manager. + +After installation, get started with one of our introductory guides: +* **[Quickstart](/gateway/{{page.release}}/get-started/quickstart/)**: An introduction to +{{site.base_gateway}}, common objects, and basic Admin API commands. +* **[Getting started guide](/gateway/{{page.release}}/get-started/comprehensive/)**: +The complete {{site.base_gateway}} +getting started guide provides in-depth examples, explanations, and step-by-step +instructions, and explores Kong's many available tools for managing the gateway. + +### Try in {{site.konnect_short_name}} + +[{{site.konnect_product_name}}](/konnect/) can manage {{site.base_gateway}} +instances. With this setup, Kong hosts the control plane and you host your +own data planes. + +There are a few ways to test out the Gateway's Plus or Enterprise features: + +* Sign up for a [free trial of {{site.konnect_product_name}} Plus](https://cloud.konghq.com/register). +* Check out learning labs at [Kong Academy]({{site.links.learn}}). +* If you are interested in evaluating Enterprise features locally, +[request a demo](https://konghq.com/get-started/#request-demo) and a Kong +representative will reach out with details to get you started. + +## Support policy +Kong follows a structured approach to versioning its products. + +For the latest version support information for {{site.ee_product_name}} and +{{site.mesh_product_name}}, see our [version support policy](/gateway/latest/support-policy/). diff --git a/app/gateway/2.7.x/install-and-run/amazon-linux.md b/app/gateway/2.7.x/install-and-run/amazon-linux.md new file mode 100644 index 000000000000..dffeb5b911e9 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/amazon-linux.md @@ -0,0 +1,98 @@ +--- +title: Install Kong Gateway on Amazon Linux +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +Kong is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A [supported system](/gateway/{{page.release}}/compatibility/) with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* (Enterprise only) A `license.json` file from Kong. + +## Download and Install + +You can install {{site.base_gateway}} by downloading an installation package or using our yum repository. + +{:.note} +> **Note:** {{site.base_gateway}} supports running on [AWS Graviton processors](https://aws.amazon.com/ec2/graviton/). It can run in all AWS Regions where AWS Graviton is supported. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on Amazon Linux from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/amzn/%{amzn}/noarch/kong-enterprise-edition-{{page.versions.ee}}.aws.noarch.rpm) +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/amzn/%{amzn}/x86_64/kong-{{page.versions.ce}}.aws.x86_64.rpm) +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package: + +{% capture install_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}}.rpm +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}}.rpm +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + +{% endnavtab %} +{% navtab YUM repository %} + +Install the YUM repository from the command line. + +1. Download the Kong YUM repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.rpm.txt?distro=amzn&codename=$(rpm --eval '%{amzn}')" | sudo tee /etc/yum.repos.d/kong-gateway-legacy.repo > /dev/null + sudo yum -q makecache -y --disablerepo='*' --enablerepo='kong-gateway-legacy' + ``` + +2. Install Kong: + +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}} +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}} +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.7.x/install-and-run/centos.md b/app/gateway/2.7.x/install-and-run/centos.md new file mode 100644 index 000000000000..ec8e4e538d5f --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/centos.md @@ -0,0 +1,94 @@ +--- +title: Install Kong Gateway on CentOS +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +Kong is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A [supported system](/gateway/{{page.release}}/compatibility/) with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* (Enterprise only) A `license.json` file from Kong + +## Download and Install + +You can install {{site.base_gateway}} by downloading an installation package or using our yum repository. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on CentOS from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/el/%{centos_ver}/x86_64/kong-enterprise-edition-{{page.versions.ee}}.el%{centos_ver}.noarch.rpm) +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/el/%{centos_ver}/x86_64/kong-{{page.versions.ce}}.el%{centos_ver}.x86_64.rpm) + ``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package using `yum`. + +{% capture install_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}}.rpm +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}}.rpm +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + +{% endnavtab %} +{% navtab YUM repository %} + +Install the YUM repository from the command line. + +1. Download the Kong YUM repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.rpm.txt?distro=el&codename=$(rpm --eval '%{rhel}')" | sudo tee /etc/yum.repos.d/kong-gateway-legacy.repo + sudo yum -q makecache -y --disablerepo='*' --enablerepo='kong-gateway-legacy' + ``` + +2. Install Kong: +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}} +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}} +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.7.x/install-and-run/debian.md b/app/gateway/2.7.x/install-and-run/debian.md new file mode 100644 index 000000000000..38b17d552797 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/debian.md @@ -0,0 +1,115 @@ +--- +title: Install Kong Gateway on Debian +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A [supported system](/gateway/{{page.release}}/compatibility/) with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* The following tools are installed: + * [`curl`](https://curl.se/) + * [`lsb-release`](https://packages.debian.org/lsb-release) + * [`apt-transport-https`](https://packages.debian.org/apt-transport-https) (Only if installing the APT repository) +* (Enterprise only) A `license.json` file from Kong. + +## Download and install + +You can install {{site.base_gateway}} by downloading an installation package or using our APT repository. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on Debian from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.all.deb "{{ site.links.direct }}/gateway-legacy/deb/debian/pool/buster/main/k/ko/kong-enterprise-edition_{{page.versions.ee}}/kong-enterprise-edition_{{page.versions.ee}}_all.deb" +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.amd64.deb "{{ site.links.direct }}/gateway-legacy/deb/debian/pool/buster/main/k/ko/kong_{{page.versions.ce}}/kong_{{page.versions.ce}}_amd64.deb" +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package: + +{% capture install_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo apt install -y ./kong-enterprise-edition-{{page.versions.ee}}.all.deb +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo apt install -y ./kong-{{page.versions.ce}}.amd64.deb +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + +{% navtabs_ee %} +{% navtab Kong Gateway %} +{:.note .no-icon} +> Once {{ site.base_gateway }} is installed, you may want to run `sudo apt-mark hold kong-enterprise-edition`. This will prevent an accidental upgrade to a new version. +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +{:.note .no-icon} +> Once {{ site.base_gateway }} is installed, you may want to run `sudo apt-mark hold kong`. This will prevent an accidental upgrade to a new version. +{% endnavtab %} +{% endnavtabs_ee %} + +{% endnavtab %} +{% navtab APT repository %} + +Install the APT repository from the command line. + +{% assign gpg_key = site.data.installation.gateway.legacy.gpg_key %} + +1. Download the Kong APT repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/gpg.{{ gpg_key }}.key" | gpg --dearmor | sudo tee -a /usr/share/keyrings/kong-gateway-legacy-archive-keyring.gpg > /dev/null + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.deb.txt?distro=debian&codename=$(lsb_release -sc)" | sudo tee /etc/apt/sources.list.d/kong-gateway-legacy.list > /dev/null + ``` +2. Update the repository: + ```bash + sudo apt-get update + ``` +3. Install Kong: + +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo apt install -y kong-enterprise-edition={{page.versions.ee}} +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo apt install -y kong={{page.versions.ce}} +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.7.x/install-and-run/docker.md b/app/gateway/2.7.x/install-and-run/docker.md new file mode 100644 index 000000000000..b77c8b0a3115 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/docker.md @@ -0,0 +1,418 @@ +--- +title: Install Kong Gateway on Docker +--- + + + + +{:.install-banner} +> See the list of Docker tags and pull the Docker image: +> * [**{{site.base_gateway}}**](https://hub.docker.com/r/kong/kong-gateway/tags){:.install-listing-link} +> * [**{{site.base_gateway}} (OSS)**](https://hub.docker.com/_/kong){:.install-listing-link} +> +> (latest {{site.base_gateway}} version: {{page.releases_hash[page.version-index].ee-version}}) + +{{site.base_gateway}} supports both PostgreSQL 9.5+ and Cassandra 3.11.* as its +datastore. This guide provides steps to configure PostgreSQL. + +If you prefer to use the open-source {{site.base_gateway}} image with Docker +Compose, Kong also provides a +[Docker Compose template](https://github.com/Kong/docker-kong/tree/master/compose) +with built-in orchestration and scalability. + +Some [older {{site.base_gateway}} images](https://support.konghq.com/support/s/article/Downloading-older-Kong-versions) +are not publicly accessible. If you need a specific patch version and can't +find it on [Kong's public Docker Hub page](https://hub.docker.com/r/kong/kong-gateway), contact +[Kong Support](https://support.konghq.com/). + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A Docker-enabled system with proper Docker access +* (Enterprise only) A `license.json` file from Kong + +Choose a path to install {{site.base_gateway}}: +* [With a database](#install-kong-gateway-with-a-database): Use a database to +store Kong entity configurations. Can use the Admin API or declarative +configuration files to configure Kong. +* [Without a database (DB-less mode)](#install-kong-gateway-in-db-less-mode): +Store Kong configuration in-memory on the node. In this mode, the Admin API is +read only, and you have to manage Kong using declarative configuration. + +If this is your first time trying out {{site.base_gateway}}, we recommend installing it +with a database. + +## Install {{site.base_gateway}} with a database + +Set up a {{site.base_gateway}} container with a PostgreSQL database to store +Kong configuration. + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + +### Prepare the database + +1. Create a custom Docker network to allow the containers to discover and +communicate with each other: + + ```sh + docker network create kong-net + ``` + + You can name this network anything you want. We use `kong-net` as + an example throughout this guide. + +1. Start a PostgreSQL container: + + ```sh + docker run -d --name kong-database \ + --network=kong-net \ + -p 5432:5432 \ + -e "POSTGRES_USER=kong" \ + -e "POSTGRES_DB=kong" \ + -e "POSTGRES_PASSWORD=kongpass" \ + postgres:9.6 + ``` + + * `POSTGRES_USER` and `POSTGRES_DB`: Set these values to `kong`. This is + the default value that {{site.base_gateway}} expects. + * `POSTGRES_PASSWORD`: Set the database password to any string. + + In this example, the PostgreSQL container named `kong-database` can + communicate with any containers on the `kong-net` network. + +1. Prepare the Kong database: + +{% capture migrations %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```sh +docker run --rm --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_PASSWORD=kongpass" \ + -e "KONG_PASSWORD=test" \ +kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine kong migrations bootstrap +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```sh +docker run --rm --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_PASSWORD=kongpass" \ +kong:{{page.releases_hash[page.version-index].ce-version}}-alpine kong migrations bootstrap +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ migrations | indent | replace: " ", "" }} + + Where: + * [`KONG_DATABASE`](/gateway/{{page.release}}/reference/configuration/#database): + Specifies the type of database that Kong is using. + * [`KONG_PG_HOST`](/gateway/{{page.release}}/reference/configuration/#postgres-settings): + The name of the PostgreSQL Docker container that is communicating over the + `kong-net` network, from the previous step. + * [`KONG_PG_PASSWORD`](/gateway/{{page.release}}/reference/configuration/#postgres-settings): + The password that you set when bringing up the PostgreSQL container in the + previous step. + * `KONG_PASSWORD` (Enterprise only): The default password for the admin + super user for {{site.base_gateway}}. + * `{IMAGE-NAME:TAG} kong migrations bootstrap`: + In order, this is the {{site.base_gateway}} container name and tag, followed by the + command to Kong to prepare the PostgreSQL database. + +### Start {{site.base_gateway}} + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + +1. Run the following command to start a container with {{site.base_gateway}}: +{% capture start_container %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```sh +docker run -d --name kong-gateway \ + --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_USER=kong" \ + -e "KONG_PG_PASSWORD=kongpass" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \ + -e "KONG_ADMIN_GUI_URL=http://localhost:8002" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 8001:8001 \ + -p 8444:8444 \ + -p 8002:8002 \ + -p 8445:8445 \ + -p 8003:8003 \ + -p 8004:8004 \ + kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```sh +docker run -d --name kong-gateway \ + --network=kong-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-database" \ + -e "KONG_PG_USER=kong" \ + -e "KONG_PG_PASSWORD=kongpass" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 127.0.0.1:8001:8001 \ + -p 127.0.0.1:8444:8444 \ + kong:{{page.releases_hash[page.version-index].ce-version}}-alpine + ``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ start_container | indent | replace: " ", "" }} + + Where: + * `--name` and `--network`: The name of the container to create, + and the Docker network it communicates on. + * [`KONG_DATABASE`](/gateway/{{page.release}}/reference/configuration/#database): + Specifies the type of database that Kong is using. + * [`KONG_PG_HOST`](/gateway/{{page.release}}/reference/configuration/#postgres-settings): + The name of the PostgreSQL Docker container that is communicating over the + `kong-net` network. + * [`KONG_PG_USER` and `KONG_PG_PASSWORD`](/gateway/{{page.release}}/reference/configuration/#postgres-settings): + The PostgreSQL username and password. {{site.base_gateway}} needs the login information + to store configuration data in the `KONG_PG_HOST` database. + * All [`_LOG`](/gateway/{{page.release}}/reference/configuration/#general-section) + parameters: set filepaths for the logs to output to, or use the values in + the example to print messages and errors to `stdout` and `stderr`. + * [`KONG_ADMIN_LISTEN`](/gateway/{{page.release}}/reference/configuration/#admin_listen): + The port that the Kong Admin API listens on for requests. + * [`KONG_ADMIN_GUI_URL`](/gateway/{{page.release}}/reference/configuration/#admin_gui_url): + (Enterprise only) The URL for accessing Kong Manager, preceded by a protocol + (for example, `http://`). + +1. Verify your installation: + + Access the `/services` endpoint using the Admin API: + + ```sh + curl -i -X GET --url http://localhost:8001/services + ``` + + You should receive a `200` status code. + +1. (Not available in OSS) Verify that Kong Manager is running by accessing it +using the URL specified in `KONG_ADMIN_GUI_URL`: + + ``` + http://localhost:8002 + ``` + +### Get started with {{site.base_gateway}} + +Now that you have a running Gateway instance, Kong provides a series of +[getting started guides](/gateway/{{page.release}}/get-started/comprehensive/) + to help you set up and enhance your first Service. + +In particular, right after installation you might want to: +* [Create a service and a route](/gateway/{{page.release}}/get-started/comprehensive/expose-services/) +* [Configure a plugin](/gateway/{{page.release}}/get-started/comprehensive/protect-services/) +* [Secure your services with authentication](/gateway/{{page.release}}/get-started/comprehensive/secure-services/) +* [Load balance traffic across targets](/gateway/{{page.release}}/get-started/comprehensive/load-balancing/) + +### Clean up containers + +If you're done testing {{site.base_gateway}} and no longer need the containers, you +can clean them up using the following commands: + +``` +docker kill kong-gateway +docker kill kong-database +docker container rm kong-gateway +docker container rm kong-database +docker network rm kong-net +``` + +## Install {{site.base_gateway}} in DB-less mode + +The following steps walk you through starting {{site.base_gateway}} in +[DB-less mode](/gateway/{{page.release}}/reference/db-less-and-declarative-config). + +### Create a Docker network + +Run the following command: + +```bash +docker network create kong-net +``` + +You can name this network anything you want. We use `kong-net` as +an example throughout this guide. + +This step is not strictly needed for running Kong in DB-less mode, but it is a good +precaution in case you want to add other things in the future (like a Rate Limiting plugin +backed up by a Redis cluster). + +### Prepare your configuration file + +1. Prepare your declarative configuration file in `.yml` or `.json` format. + + The syntax and properties are + described in the [Declarative Configuration format] guide. Add whatever core + entities (Services, Routes, Plugins, Consumers, etc) you need to this file. + + For example, a simple file with a Service and a Route + could look something like this: + + ```yaml + _format_version: "1.1" + _transform: true + + services: + - host: httpbin.konghq.com + name: example_service + port: 80 + protocol: http + routes: + - name: example_route + paths: + - /mock + strip_path: true + ``` + + This guide assumes you named the file `kong.yml`. + +1. Save your declarative configuration locally, and note the filepath. + +### Start {{site.base_gateway}} in DB-less mode + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + +1. From the same directory where you just created the `kong.yml` file, +run the following command to start a container with {{site.base_gateway}}: + +{% capture start_container %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```sh +docker run -d --name kong-dbless \ + --network=kong-net \ + -v "$(pwd):/kong/declarative/" \ + -e "KONG_DATABASE=off" \ + -e "KONG_DECLARATIVE_CONFIG=/kong/declarative/kong.yml" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \ + -e "KONG_ADMIN_GUI_URL=http://localhost:8002" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 8001:8001 \ + -p 8444:8444 \ + -p 8002:8002 \ + -p 8445:8445 \ + -p 8003:8003 \ + -p 8004:8004 \ + kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```sh +docker run -d --name kong-dbless \ + --network=kong-net \ + -v "$(pwd):/kong/declarative/" \ + -e "KONG_DATABASE=off" \ + -e "KONG_DECLARATIVE_CONFIG=/kong/declarative/kong.yml" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 127.0.0.1:8001:8001 \ + -p 127.0.0.1:8444:8444 \ + kong:{{page.releases_hash[page.version-index].ce-version}}-alpine + ``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ start_container | indent | replace: " ", "" }} + + Where: + * `--name` and `--network`: The name of the container to create, + and the Docker network it communicates on. + * `-v $(pwd):/path/to/target/`: Mount the current directory on your + local filesystem to a directory in the Docker container. This makes the + `kong.yml` file visible from the Docker container. + * [`KONG_DATABASE`](/gateway/{{page.release}}/reference/configuration/#database): + Sets the database to `off` to tell Kong not to use any + backing database for configuration storage. + * [`KONG_DECLARATIVE_CONFIG`](/gateway/{{page.release}}/reference/configuration/#declarative_config): + The path to a declarative configuration file inside the container. + This path should match the target path that you're mapping with `-v`. + * All [`_LOG`](/gateway/{{page.release}}/reference/configuration/#general-section) + parameters: set filepaths for the logs to output to, or use the values in + the example to print messages and errors to `stdout` and `stderr`. + * [`KONG_ADMIN_LISTEN`](/gateway/{{page.release}}/reference/configuration/#admin_listen): + The port that the Kong Admin API listens on for requests. + * [`KONG_ADMIN_GUI_URL`](/gateway/{{page.release}}/reference/configuration/#admin_gui_url): + (Enterprise only) The URL for accessing Kong Manager, preceded by a protocol + (for example, `http://`). + +1. Verify that {{site.base_gateway}} is running: + + ```sh + curl -i http://localhost:8001 + ``` + + Test an endpoint. For example, get a list of services: + + ```sh + curl -i http://localhost:8001/services + ``` + +[DB-less mode]: /gateway/{{page.release}}/reference/db-less-and-declarative-config/ +[Declarative Configuration format]: /gateway/{{page.release}}/reference/db-less-and-declarative-config/#the-declarative-configuration-format +[Docker Volume]: https://docs.docker.com/storage/volumes/ + +### Get started with {{site.base_gateway}} + +Now that you have a running Gateway instance, Kong provides a series of +[getting started guides](/gateway/{{page.release}}/get-started/comprehensive/) +to help you set up and enhance your first Service. + +If you use the sample `kong.yml` in this guide, you already have a Service and +a Route configured. Here are a few more things to check out: +* [Configure a plugin](/gateway/{{page.release}}/get-started/comprehensive/protect-services/?tab=using-deck-yaml/) +* [Secure your services with authentication](/gateway/{{page.release}}/get-started/comprehensive/secure-services/?tab=using-deck-yaml/) +* [Load balance traffic across targets](/gateway/{{page.release}}/get-started/comprehensive/load-balancing/?tab=using-deck-yaml/) + +### Clean up containers + +If you're done testing {{site.base_gateway}} and no longer need the containers, you +can clean them up using the following commands: + +``` +docker kill kong-dbless +docker container rm kong-dbless +docker network rm kong-net +``` + +## Troubleshooting + +If you did not receive a `200 OK` status code or need assistance completing +setup, reach out to your support contact or head over to the +[Support Portal](https://support.konghq.com/support/s/). diff --git a/app/gateway/2.7.x/install-and-run/helm.md b/app/gateway/2.7.x/install-and-run/helm.md new file mode 100644 index 000000000000..00fe3e13450d --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/helm.md @@ -0,0 +1,197 @@ +--- +title: Install on Kubernetes with Helm +--- + +This page explains how to install {{site.base_gateway}} with {{site.kic_product_name}} using Helm. + +* The Enterprise deployment includes a PostgreSQL sub-chart provided by Bitnami. +* For open-source deployments, you can choose to use the PostgreSQL sub-chart, or install without a database. + +Configuration for both options is flexible and depends on your environment. + +The documentation on installing with a [flat Kubernetes manifest](/gateway/{{page.release}}/install-and-run/kubernetes/) also explains how to install in DB-less mode for both Enterprise and OSS deployments. + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +- A Kubernetes cluster v1.19 or later +- `kubectl` v1.19 or later +- (Enterprise only) A `license.json` file from Kong +- Helm 3 + +## Create namespace + +Create the namespace for {{site.base_gateway}} with {{site.kic_product_name}}. For example: + +```sh +kubectl create namespace kong +``` + +## Set up Helm + +1. Add the Kong charts repository: + + ```sh + helm repo add kong https://charts.konghq.com + ``` + +1. Update Helm: + + ```sh + helm repo update + ``` + +## Create license secret +{:.badge .enterprise} + +1. Save your license file temporarily with the filename `license` (no file extension). + +1. Run: + + ```sh + kubectl create secret generic kong-enterprise-license --from-file=./license -n kong + ``` + +## Create secret for RBAC superuser (recommended) +{:.badge .enterprise} + +If you plan to use RBAC, you must create a secret for the superuser account password at this step in installation. You cannot create it later. + +1. Create the RBAC account. + +1. Create the secret: + + ```sh + kubectl create secret generic kong-enterprise-superuser-password \ + -n kong \ + --from-literal=password={YOUR_PASSWORD} + ``` + +## Create secret for Session plugin +{:.badge .enterprise} + +If you create an RBAC superuser and plan to work with Kong Manager or Dev Portal, you must also configure the Session plugin and store its config in a Kubernetes secret: + +1. Create a session config file for Kong Manager: + + ```bash + $ echo '{"cookie_name":"admin_session","cookie_samesite":"off","secret":"","cookie_secure":false,"storage":"kong"}' > admin_gui_session_conf + ``` + +1. Create a session config file for Kong Dev Portal: + + ```bash + $ echo '{"cookie_name":"portal_session","cookie_samesite":"off","secret":"","cookie_secure":false,"storage":"kong"}' > portal_session_conf + ``` + + Or, if you have different subdomains for the `portal_api_url` and `portal_gui_host`, set the `cookie_domain` + and `cookie_samesite` properties as follows: + + ``` + $ echo '{"cookie_name":"portal_session","cookie_samesite":"off","cookie_domain":"<.your_subdomain.com>","secret":"","cookie_secure":false,"storage":"kong"}' > portal_session_conf + ``` + +1. Create the secret: + + For Kong Manager only: + + ```sh + kubectl create secret generic kong-session-config \ + -n kong \ + --from-file=admin_gui_session_conf + ``` + + For Kong Manager and Dev Portal: + + ```sh + kubectl create secret generic kong-session-config \ + -n kong \ + --from-file=admin_gui_session_conf \ + --from-file=portal_session_conf + ``` + +## Create values.yaml file + +Create a `values.yaml` file to provide required values such as password secrets or optional email addresses for notifications. You can work from the [Enterprise example file](https://github.com/Kong/charts/blob/main/charts/kong/example-values/full-k4k8s-with-kong-enterprise.yaml). The example file includes comments to explain which values you must set. + +For OSS deployments, the default install might be sufficient, but you can explore other `values.yaml` files and [the readme in the charts repository](https://github.com/Kong/charts/blob/main/charts/kong/README.md), which includes an exhaustive list of all possible configuration properties. + +Note that the Enterprise deployment includes a PostgreSQL sub-chart provided by Bitnami. You might need to delete the PersistentVolume objects for PostgreSQL in your Kubernetes cluster to connect to the database after install. + +## Deploy {{site.base_gateway}} with {{site.kic_product_name}} + +1. Run: + + ```sh + ## {{site.base_gateway}} + helm install my-kong kong/kong -n kong --values ./values.yaml + ``` + + ```sh + ## {{site.base_gateway}} (OSS) + helm install kong/kong --generate-name --set ingressController.installCRDs=false + ``` + + For more information on working with Helm charts for {{site.ce_product_name}}, see the [chart documentation](https://github.com/Kong/charts/blob/main/charts/kong/README.md). + + This might take some time. + +1. Check pod status, and make sure the `my-kong-kong-{ID}` pod is running: + + ```bash + kubectl get pods -n kong + ``` + +## Finalize configuration and verify installation +{:.badge .enterprise} + +1. Run: + + ```sh + kubectl get svc my-kong-kong-admin \ + -n kong \ + --output=jsonpath='{.status.loadBalancer.ingress[0].ip}' + ``` + +1. Copy the IP address from the output, then add the following to the `.env` section of your `values.yaml` file: + + ```yaml + admin_api_uri: {YOUR-DNS-OR-IP} + ``` + + {:.note} + > **Note:** If you configure RBAC, you must specify a DNS hostname instead of an IP address. + +1. Clean up: + + ```sh + kubectl delete jobs -n kong --all + ``` + +1. Update with changed `values.yaml`: + + ``` + helm upgrade my-kong kong/kong -n kong --values ./values.yaml + ``` + +1. After the upgrade finishes, run: + + ``` + kubectl get svc -n kong + ``` + + With an Enterprise deployment, the output includes `EXTERNAL-IP` values for Kong Manager and Dev Portal. For example: + + ```sh + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + my-kong-kong-manager LoadBalancer 10.96.61.116 10.96.61.116 8002:31308/TCP,8445:32420/TCP 24m + my-kong-kong-portal LoadBalancer 10.101.251.123 10.101.251.123 8003:31609/TCP,8446:32002/TCP 24m + ``` + +## Next steps + +See the [{{site.kic_product_name}} docs](/kubernetes-ingress-controller/) for how-to guides, reference guides, and more. diff --git a/app/gateway/2.7.x/install-and-run/index.md b/app/gateway/2.7.x/install-and-run/index.md new file mode 100644 index 000000000000..a49b8ccf93c5 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/index.md @@ -0,0 +1,76 @@ +--- +title: Install Kong Gateway +disable_image_expand: true +--- + + + +## Deployment options + +{% include_cached /md/gateway/deployment-options.md release=page.release %} + +## Installation paths + +Some installation topics provide multiple package types and installation options. +Choose your preferred mode when following installation steps: + +* **Open-source**: Follow installation instructions and skip any Free or Enterprise steps. +* **Free Mode**: Install {{site.base_gateway}} without a license, gaining access to Kong Manager. +* **Enterprise**: Install {{site.base_gateway}} and add a license. + +If you install the {{site.base_gateway}} (not open-source), you can add a license +at any time to gain access to Enterprise features. + +{:.note} +> **Note**: For deployments on Kubernetes (including Helm and OpenShift), +you need to apply the license during installation. + +See [{{site.base_gateway}} Licensing](/gateway/latest/plan-and-deploy/licenses/) for a feature comparison +between Free Mode and the Enterprise subscription, and more information about licenses. diff --git a/app/gateway/2.7.x/install-and-run/kubernetes.md b/app/gateway/2.7.x/install-and-run/kubernetes.md new file mode 100644 index 000000000000..bae8541ac667 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/kubernetes.md @@ -0,0 +1,109 @@ +--- +title: Install on Kubernetes +--- + +This page explains how to install {{site.base_gateway}} with {{site.kic_product_name}} in DB-less mode. To install with a database, see the documentation on installing with [Helm](/gateway/{{page.release}}/install-and-run/helm/). + +This page also includes the equivalent commands for OpenShift. + +Note that in DB-less mode on Kubernetes, config is stored in etcd, the Kubernetes native datastore. For more information see [Kubernetes Deployment Options](/gateway/{{page.release}}/plan-and-deploy/kubernetes-deployment-options/). + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +- A Kubernetes cluster v1.19 or later +- `kubectl` v1.19 or later +- (Enterprise only) A `license.json` file from Kong + +## Create namespace + +Create the namespace for {{site.base_gateway}} with {{site.kic_product_name}}. For example: + +```sh +## on Kubernetes native +kubectl create namespace kong +``` + +```sh +## on OpenShift +oc new-project kong +``` + +## Create license secret +{:.badge .enterprise} + +1. Save your license file temporarily with the filename `license` (no file extension). + +1. Run: + + ```sh + ## on Kubernetes native + kubectl create secret generic kong-enterprise-license --from-file=./license -n kong + ``` + + ```sh + ## on OpenShift + oc create secret generic kong-enterprise-license --from-file=./license -n kong + ``` + +## Deploy + +1. Run one of the following: + + ```sh + ## {{site.base_gateway}} on Kubernetes native + kubectl apply -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v{{site.data.kong_latest_KIC.version}}/deploy/single/all-in-one-dbless-k4k8s-enterprise.yaml + ``` + + ```sh + ## {{site.base_gateway}} on OpenShift + oc create -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v{{site.data.kong_latest_KIC.version}}/deploy/single/all-in-one-dbless-k4k8s-enterprise.yaml + ``` + + ```sh + ## {{site.base_gateway}} (OSS) on Kubernetes native + kubectl apply -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v{{site.data.kong_latest_KIC.version}}/deploy/single/all-in-one-dbless.yaml + ``` + + This might take a few minutes. + +1. Check the install status: + + ```sh + kubectl get pods -n kong + ``` + + or: + + ```sh + oc get pods -n kong + ``` + +1. To make HTTP requests, you need the IP address of the load balancer. Get the LoadBalancer address and store it in a local PROXY_IP environment variable: + + ```sh + export PROXY_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" service -n kong kong-proxy) + ``` + +1. Check that the value of $PROXY_IP is the value of the external host: + + ```sh + kubectl get service kong-proxy -n kong + ``` + + or: + + ```sh + oc get service kong-proxy -n kong + ``` + + {:.note} + > **Note:** Some cluster providers provide only a DNS name for load balancers. In this case, specify `.hostname` instead of `.ip`. + +## Next steps + +See the [{{site.kic_product_name}} docs](/kubernetes-ingress-controller/) for how-to guides, reference guides, and more. diff --git a/app/gateway/2.7.x/install-and-run/migrate-ce-to-ke.md b/app/gateway/2.7.x/install-and-run/migrate-ce-to-ke.md new file mode 100644 index 000000000000..70ba16985f31 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/migrate-ce-to-ke.md @@ -0,0 +1,40 @@ +--- +title: Migrating from Kong Gateway (OSS) to Kong Gateway +toc: true +--- + +As of {{site.ee_product_name}} version 2.1.x and later, it is no longer necessary to explicitly +run the `migrate-community-to-enterprise` command parameter to migrate all +{{site.ce_product_name}} entities to {{site.ee_product_name}}. Running the `kong migrations` commands +performs that migration command on your behalf. + +{:.note} +> **Important:** You can only migrate to a {{site.ee_product_name}} version that +supports the same {{site.ce_product_name}} version. + +## Prerequisites + +{:.warning} +> **Warning:** This action is irreversible, therefore it is strongly + recommended to back up your production data before migrating from + {{site.ce_product_name}} to {{site.ee_product_name}}. + +* If running a version of {{site.ce_product_name}} earlier than 2.7.x, + [upgrade to Kong 2.7.x](/gateway/{{page.release}}/install-and-run/upgrade-oss/) before migrating + {{site.ce_product_name}} to {{site.ee_product_name}} 2.7.x. + +## Migration steps + +The following steps guide you through the migration process. + +1. Download {{site.ee_product_name}} 2.7.x and configure it to point to the + same datastore as your {{site.ce_product_name}} 2.7.x node. The migration + command expects the datastore to be up-to-date on any pending migration: + + ```shell + kong migrations up [-c configuration_file] + kong migrations finish [-c configuration_file] + ``` + +2. Confirm that all of the entities are now available on your + {{site.ee_product_name}} node. diff --git a/app/gateway/2.7.x/install-and-run/openshift.md b/app/gateway/2.7.x/install-and-run/openshift.md new file mode 100644 index 000000000000..dc7bf21c1c73 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/openshift.md @@ -0,0 +1,179 @@ +--- +title: Install on OpenShift with Helm +badge: enterprise +--- + +This page explains how to install {{site.base_gateway}} with {{site.kic_product_name}} with a database. To install in DB-less mode, see the documentation on installing with a [flat Kubernetes manifest](/gateway/{{page.release}}/install-and-run/kubernetes/). + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +{{site.ce_product_name}} is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + + +## Prerequisites + +- A Kubernetes cluster v1.19 or later +- `kubectl` v1.19 or later +- (Enterprise only) A `license.json` file from Kong +- Helm 3 + +## Create namespace + +Create the namespace for {{site.base_gateway}} with {{site.kic_product_name}}. For example: + +```sh +oc new-project kong +``` + +## Create license secret + +1. Save your license file temporarily with the filename `license` (no file extension). + +1. Run: + + ```sh + oc create secret generic kong-enterprise-license -n kong --from-file=./license + ``` + +## Set up Helm + +1. Add the Kong charts repository: + + ```sh + helm repo add kong https://charts.konghq.com + ``` + +1. Update Helm: + + ```sh + helm repo update + ``` + +## Create secret for RBAC superuser (recommended) +{:.badge .enterprise} + +If you plan to use RBAC, you must create the superuser account at this step in installation. You cannot create it later. + +1. Create the RBAC account. + +1. Create the secret: + + ```sh + oc create secret generic kong-enterprise-superuser-password \ + -n kong \ + --from-literal=password={your-password} + ``` + +## Create secret for Session plugin + +If you create an RBAC superuser and plan to work with Kong Manager or Dev Portal, you must also configure the Session plugin and store its config in a Kubernetes secret: + +1. Create a session config file for Kong Manager: + + ```bash + $ echo '{"cookie_name":"admin_session","cookie_samesite":"off","secret":"","cookie_secure":false,"storage":"kong"}' > admin_gui_session_conf + ``` + +1. Create a session config file for Kong Dev Portal: + + ```bash + $ echo '{"cookie_name":"portal_session","cookie_samesite":"off","secret":"","cookie_secure":false,"storage":"kong"}' > portal_session_conf + ``` + + Or, if you have different subdomains for the `portal_api_url` and `portal_gui_host`, set the `cookie_domain` + and `cookie_samesite` properties as follows: + + ``` + $ echo '{"cookie_name":"portal_session","cookie_samesite":"off","cookie_domain":"<.your_subdomain.com>","secret":"","cookie_secure":false,"storage":"kong"}' > portal_session_conf + ``` + +1. Create the secret: + + For Kong Manager only: + + ```sh + oc create secret generic kong-session-config \ + -n kong \ + --from-file=admin_gui_session_conf + ``` + + For Kong Manager and Dev Portal: + + ```sh + oc create secret generic kong-session-config \ + -n kong \ + --from-file=admin_gui_session_conf \ + --from-file=portal_session_conf + ``` + +## Create values.yaml file + +Create a `values.yaml` file to provide required values such as password secrets or optional email addresses for notifications. Work from the [Enterprise example file](https://github.com/Kong/charts/blob/main/charts/kong/example-values/full-k4k8s-with-kong-enterprise.yaml). The example file includes comments to explain which values you must set. The [readme in the charts repository](https://github.com/Kong/charts/blob/main/charts/kong/README.md) includes an exhaustive list of all possible configuration properties. + +Note that this deployment includes a PostgreSQL sub-chart provided by Bitnami. You might need to delete the PersistentVolume objects for PostgreSQL in your Kubernetes cluster to connect to the database after install. + +## Deploy {{site.base_gateway}} with {{site.kic_product_name}} + +1. Run: + + ```sh + helm install my-kong kong/kong -n kong --values ./values.yaml + ``` + + This might take some time. + +1. Check pod status, and make sure the `my-kong-kong-` pod is running: + + ```bash + oc get pods -n kong + ``` + +## Finalize configuration and verify installation + +1. Run: + + ```sh + oc get svc my-kong-kong-admin \ + -n kong \ + --output=jsonpath='{.status.loadBalancer.ingress[0].ip}' + ``` + +1. Copy the IP address from the output, then add the following to the `.env` section of your `values.yaml` file: + + ```yaml + admin_api_uri: + ``` + + {:.note} + > **Note:** If you configure RBAC, you must specify a DNS hostname instead of an IP address. + +1. Clean up: + + ```sh + oc delete jobs -n kong --all + ``` + +1. Update with changed `values.yaml`: + + ``` + helm upgrade my-kong kong/kong -n kong --values ./values.yaml + ``` + +1. After the upgrade finishes, run: + + ``` + oc get svc -n kong + ``` + + The output includes `EXTERNAL-IP` values for Kong Manager and Dev Portal. For example: + + ```sh + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + my-kong-kong-manager LoadBalancer 10.96.61.116 10.96.61.116 8002:31308/TCP,8445:32420/TCP 24m + my-kong-kong-portal LoadBalancer 10.101.251.123 10.101.251.123 8003:31609/TCP,8446:32002/TCP 24m + ``` + +## Next steps + +See the [{{site.kic_product_name}} docs](/kubernetes-ingress-controller/) for how-to guides, reference guides, and more. diff --git a/app/gateway/2.7.x/install-and-run/rhel.md b/app/gateway/2.7.x/install-and-run/rhel.md new file mode 100644 index 000000000000..74f87c258363 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/rhel.md @@ -0,0 +1,111 @@ +--- +title: Install Kong Gateway on RHEL +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +Kong is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A [supported system](/gateway/{{page.release}}/compatibility/) with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* (Enterprise only) A `license.json` file from Kong + +## Download and Install + +You can install {{site.base_gateway}} by downloading an installation package or using our yum repository. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on RHEL from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/el/%{rhel}/noarch/kong-enterprise-edition-{{page.versions.ee}}.el%{rhel}.noarch.rpm) +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.rpm $(rpm --eval {{ site.links.direct }}/gateway-legacy/rpm/el/%{rhel}/x86_64/kong-{{page.versions.ce}}.el%{rhel}.x86_64.rpm) + ``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package using `yum` or `rpm`. + + If you use the `rpm` install method, the packages _only_ contain {{site.base_gateway}}. They don't include any dependencies. + +{% capture install_package %} +{% navtabs %} +{% navtab yum %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}}.rpm +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}}.rpm +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endnavtab %} +{% navtab rpm %} + +{:.important} +> The `rpm` method is only available for open-source packages. For the `kong-enterprise-edition` package, use `yum`. + +```bash +rpm -iv kong-{{page.versions.ce}}.rpm +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + + Installing directly using `rpm` is suitable for Red Hat's [Universal Base Image](https://developers.redhat.com/blog/2020/03/24/red-hat-universal-base-images-for-docker-users) "minimal" variant. You will need to install Kong's dependencies separately via `microdnf`. + +{% endnavtab %} +{% navtab YUM repository %} + +Install the YUM repository from the command line. + +1. Download the Kong YUM repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.rpm.txt?distro=el&codename=$(rpm --eval '%{rhel}')" | sudo tee /etc/yum.repos.d/kong-gateway-legacy.repo + sudo yum -q makecache -y --disablerepo='*' --enablerepo='kong-gateway-legacy' + ``` + +2. Install Kong: +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo yum install -y kong-enterprise-edition-{{page.versions.ee}} +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo yum install -y kong-{{page.versions.ce}} +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.7.x/install-and-run/ubuntu.md b/app/gateway/2.7.x/install-and-run/ubuntu.md new file mode 100644 index 000000000000..55bb29988e51 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/ubuntu.md @@ -0,0 +1,116 @@ +--- +title: Install Kong Gateway on Ubuntu +--- + +The {{site.base_gateway}} software is governed by the +[Kong Software License Agreement](https://konghq.com/kongsoftwarelicense). +Kong is licensed under an +[Apache 2.0 license](https://github.com/Kong/kong/blob/master/LICENSE). + +## Prerequisites + +* A supported system with root or [root-equivalent](/gateway/{{page.release}}/plan-and-deploy/kong-user/) access. +* (Enterprise only) A `license.json` file from Kong + +## Download and install + +You can install {{site.base_gateway}} by downloading an installation package or using our APT repository. + +{% navtabs %} +{% navtab Package %} + +Install {{site.base_gateway}} on Ubuntu from the command line. + +1. Download the Kong package: + +{% capture download_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +curl -Lo kong-enterprise-edition-{{page.versions.ee}}.all.deb "{{ site.links.direct }}/gateway-legacy/deb/ubuntu/pool/xenial/main/k/ko/kong-enterprise-edition_{{page.versions.ee}}/kong-enterprise-edition_{{page.versions.ee}}_all.deb" +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +curl -Lo kong-{{page.versions.ce}}.all.deb "{{ site.links.direct }}/gateway-legacy/deb/ubuntu/pool/xenial/main/k/ko/kong_{{page.versions.ce}}/kong_{{page.versions.ce}}_amd64.deb" +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ download_package | indent | replace: " ", "" }} + +2. Install the package: + +{% capture install_package %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo apt install -y ./kong-enterprise-edition-{{page.versions.ee}}.all.deb +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo apt install -y ./kong-{{page.versions.ce}}.all.deb +``` +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_package | indent | replace: " ", "" }} + +{% endnavtab %} +{% navtab APT repository %} + +Install the APT repository from the command line. + +{% assign gpg_key = site.data.installation.gateway.legacy.gpg_key %} + +1. Setup the Kong APT repository: + ```bash + curl -1sLf "{{ site.links.direct }}/gateway-legacy/gpg.{{ gpg_key }}.key" | gpg --dearmor | sudo tee -a /usr/share/keyrings/kong-gateway-legacy-archive-keyring.gpg > /dev/null + curl -1sLf "{{ site.links.direct }}/gateway-legacy/config.deb.txt?distro=ubuntu&codename=xenial" | sudo tee /etc/apt/sources.list.d/kong-gateway-legacy.list > /dev/null + ``` + +2. Update the repository: + ```bash + sudo apt-get update + ``` + +3. Install Kong: + +{% capture install_from_repo %} +{% navtabs_ee codeblock %} +{% navtab Kong Gateway %} +```bash +sudo apt install -y kong-enterprise-edition={{page.versions.ee}} +``` + +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +sudo apt install -y kong={{page.versions.ce}} +``` + + +{% endnavtab %} +{% endnavtabs_ee %} +{% endcapture %} + +{{ install_from_repo | indent | replace: " ", "" }} + +{% navtabs_ee %} +{% navtab Kong Gateway %} +{:.note .no-icon} +> Once {{ site.base_gateway }} is installed, you may want to run `sudo apt-mark hold kong-enterprise-edition`. This will prevent an accidental upgrade to a new version. +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +{:.note .no-icon} +> Once {{ site.base_gateway }} is installed, you may want to run `sudo apt-mark hold kong`. This will prevent an accidental upgrade to a new version. +{% endnavtab %} +{% endnavtabs_ee %} + +{% endnavtab %} +{% endnavtabs %} + +{% include_cached /md/gateway/setup.md release=page.release %} diff --git a/app/gateway/2.7.x/install-and-run/upgrade-enterprise.md b/app/gateway/2.7.x/install-and-run/upgrade-enterprise.md new file mode 100644 index 000000000000..b49ffa907058 --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/upgrade-enterprise.md @@ -0,0 +1,225 @@ +--- +title: Upgrade Kong Gateway +badge: free +--- + +Upgrade to major, minor, and patch {{site.ee_product_name}} (Enterprise package) +releases using the `kong migrations` commands. + +You can also use the commands to migrate all {{site.ce_product_name}} entities +to {{site.ee_product_name}}. See +[Migrating from {{site.ce_product_name}} to {{site.base_gateway}}](/gateway/{{page.release}}/install-and-run/migrate-ce-to-ke/). + +If you experience any issues when running migrations, contact +[Kong Support](https://support.konghq.com/support/s/) for assistance. + +## Upgrade path for {{site.base_gateway}} releases + +Kong follows a structured approach to versioning its products, which makes a +distinction between major, minor, and patch versions. The upgrade +path for major and minor versions differs depending on the previous version +from which you are migrating: + +- If you are migrating from 2.x.x, upgrading to 2.7.x is a +**minor** upgrade. You can upgrade from any 2.1.x or later version directly to +2.7.x. + +- If you are migrating from 1.x.x, upgrading to 2.7.x is a **major** +upgrade. While you can upgrade directly to the latest version, be aware of any +breaking changes between the 1.x and 2.x series noted in this document and in +the Gateway changelogs. + + See specific breaking changes in the {{site.base_gateway}} changelogs: + [open-source (OSS)](https://github.com/Kong/kong/blob/2.0.0/CHANGELOG.md#200) and + [Enterprise](/gateway/changelog/#2131). Since {{site.base_gateway}} is built on an + open-source foundation, any breaking changes in OSS affect all Gateway packages. + +In either case, you can review the [upgrade considerations](#upgrade-considerations), +then follow the [database migration](#migrate-db) instructions. + +## Upgrade considerations + +Before upgrading, review this list for any configuration or breaking changes that +affect your current installation. + +If you are adding a new plugin to your installation, you need to run +`kong migrations up` with the plugin name specified. For example, +`KONG_PLUGINS=oauth2`. + +### Kong Manager breaking changes + +Version 2.7.x introduced a new way to configure the OIDC plugin to map IdP roles to Kong Manager admin accounts. +You must now specify the `admin_claim` instead of the `consumer_claim` in your OIDC config file. For more information, +see [OIDC Authenticated Group Mapping](/gateway/{{page.release}}/configure/auth/kong-manager/oidc-mapping/). + +### Dev Portal migrations + +There are no migrations necessary for the Dev Portal when upgrading from 2.6.x to +2.7.x. + +If you are currently using the Dev Portal in 1.5.x or earlier, +[manually migrate the files](/enterprise/2.1.x/developer-portal/latest-migrations) +to version 2.1.x before continuing. + +### Hybrid mode considerations + +{:.important} +> **Important:** If you are currently running in [hybrid mode](/gateway/{{page.release}}/plan-and-deploy/hybrid-mode/), +upgrade the control plane first, and then the data planes. + +* If you are currently running 2.6.x in classic (traditional) + mode and want to run in hybrid mode instead, follow the hybrid mode + [installation instructions](/gateway/{{page.release}}/plan-and-deploy/hybrid-mode/hybrid-mode-setup/) + after running the migration. +* Custom plugins (either your own plugins or third-party plugins that are not shipped with Kong) + need to be installed on both the control plane and the data planes in hybrid mode. Install the + plugins on the control plane first, and then the data planes. +* The [Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced/) plugin does not + support the `cluster` strategy in hybrid mode. The `redis` strategy must be used instead. + +### Kong for Kubernetes considerations + +The Helm chart automates the upgrade migration process. When running `helm upgrade`, +the chart spawns an initial job to run `kong migrations up` and then spawns new +Kong pods with the updated version. Once these pods become ready, they begin processing +traffic and old pods are terminated. Once this is complete, the chart spawns another job +to run `kong migrations finish`. + +While the migrations themselves are automated, the chart does not automatically ensure +that you follow the recommended upgrade path. If you are upgrading from more than one minor +Kong version back, check the upgrade path recommendations for Kong open source or {{site.base_gateway}}. + +Although not required, users should upgrade their chart version and Kong version independently. +In the event of any issues, this will help clarify whether the issue stems from changes in +Kubernetes resources or changes in Kong. + +For specific Kong for Kubernetes version upgrade considerations, see +[Upgrade considerations](https://github.com/Kong/charts/blob/main/charts/kong/UPGRADE.md) + +#### Kong deployment split across multiple releases + +The standard chart upgrade automation process assumes that there is only a single Kong release +in the Kong cluster, and runs both `migrations up` and `migrations finish` jobs. + +If you split your Kong deployment across multiple Helm releases (to create proxy-only +and admin-only nodes, for example), you must set which migration jobs run based on your +upgrade order. + +To handle clusters split across multiple releases, you should: + +1. Upgrade one of the releases with: + + ```shell + helm upgrade RELEASENAME -f values.yaml \ + --set migrations.preUpgrade=true \ + --set migrations.postUpgrade=false + ``` +2. Upgrade all but one of the remaining releases with: + + ```shell + helm upgrade RELEASENAME -f values.yaml \ + --set migrations.preUpgrade=false \ + --set migrations.postUpgrade=false + ``` +3. Upgrade the final release with: + + ```shell + helm upgrade RELEASENAME -f values.yaml \ + --set migrations.preUpgrade=false \ + --set migrations.postUpgrade=true + ``` + +This ensures that all instances are using the new Kong package before running +`kong migrations finish`. + +## Upgrade from 1.x.x - 2.6.x to 2.7.x {#migrate-db} + +{{site.ee_product_name}} supports the zero downtime migration model. This means +that while the migration is in process, you have two Kong clusters with different +versions running that are sharing the same database. This is sometimes referred +to as the +[blue-green migration model](https://en.wikipedia.org/wiki/Blue-green_deployment). + +The migrations are designed so that there is no need to fully copy +the data. The new version of {{site.ee_product_name}} is able to use the data as it +is migrated, and the old Kong cluster keeps working until it is finally time to +decommission it. For this reason, the full migration is split into two commands: + +- `kong migrations up`: performs only non-destructive operations +- `kong migrations finish`: puts the database in the final expected state (DB-less + mode is not supported in {{site.ee_product_name}}) + +Follow the instructions for your backing data store to migrate to the new version. +If you prefer to use a fresh data store and only migrate your `kong.conf` file, +see the instructions to +[install 2.7.x on a fresh datastore](#install-27x-on-a-fresh-datastore). + +### PostgreSQL + +1. Download 2.7.x, and configure it to point to the same + datastore as your old (1.x.x-2.x.x) cluster. +2. Run `kong migrations up`. +3. After that finishes running, both the old (1.x.x-2.x.x) and new (2.7.x) clusters can + now run simultaneously on the same datastore. Start provisioning 2.7.x nodes, + but do _not_ use their Admin API yet. + + {:.important} + > **Important:** If you need to make Admin API requests, + these should be made to the old cluster's nodes. This prevents + the new cluster from generating data that is not understood by the old + cluster. + +4. Gradually divert traffic away from your old nodes, and redirect traffic to + your 2.7.x cluster. Monitor your traffic to make sure everything + is going smoothly. +5. When your traffic is fully migrated to the 2.7.x cluster, decommission your + old nodes. +6. From your 2.7.x cluster, run `kong migrations finish`. From this point onward, + it is no longer possible to start nodes in the old cluster + that still points to the same datastore. + + Run this command _only_ when you are + confident that your migration was successful. From now on, you can safely make + Admin API requests to your 2.7.x nodes. + +### Cassandra + +Due to internal changes, the table schemas used by {{site.ee_product_name}} 2.7.x on Cassandra +are incompatible with those used by {{site.ee_product_name}} 2.1.x or lower. Migrating using the usual commands +`kong migrations up` and `kong migrations finish` will require a small +window of downtime, since the old and new versions cannot use the +database at the same time. + +Alternatively, to keep your previous version fully operational while the new +one initializes, transfer the data to a new keyspace using a database dump, as +described below: + +1. Download 2.7.x, and configure it to point to a new keyspace. + +2. Run `kong migrations bootstrap`. + + Once that finishes running, both the old (1.x.x-2.1.x) and new (2.7.x) + clusters can now run simultaneously, but the new cluster does not + have any data yet. +3. On the old cluster, run `kong config db_export`. This will create + a file named `kong.yml` with a database dump. +4. Transfer the file to the new cluster and run + `kong config db_import kong.yml`. This will load the data into the new cluster. +5. Gradually divert traffic away from your old nodes, and into + your 2.7.x cluster. Monitor your traffic to make sure everything + is going smoothly. +6. When your traffic is fully migrated to the 2.7.x cluster, + decommission your old nodes. + +### Install 2.7.x on a fresh datastore + +For installing on a fresh datastore, {{site.ee_product_name}} 2.7.x has the +`kong migrations bootstrap` command. Run the following commands to +prepare a new 2.7.x cluster from a fresh datastore. By default, the `kong` CLI tool +loads the configuration from `/etc/kong/kong.conf`, but you can optionally use +the `-c` flag to indicate the path to your configuration file: + +```bash +$ kong migrations bootstrap [-c /path/to/kong.conf] +$ kong start [-c /path/to/kong.conf] +``` diff --git a/app/gateway/2.7.x/install-and-run/upgrade-oss.md b/app/gateway/2.7.x/install-and-run/upgrade-oss.md new file mode 100644 index 000000000000..de7d59f4e62f --- /dev/null +++ b/app/gateway/2.7.x/install-and-run/upgrade-oss.md @@ -0,0 +1,198 @@ +--- +# Generated via autodoc/upgrading/generate.lua in the kong/kong repo +title: Upgrade Kong Gateway OSS +badge: oss +source_url: https://github.com/Kong/kong/blob/master/UPGRADE.md +--- + +This document guides you through the process of upgrading {{site.ce_product_name}} to the **latest version**. +To upgrade to prior versions, find the version number in the +[Upgrade doc in GitHub](https://github.com/Kong/kong/blob/master/UPGRADE.md). + +## Upgrade to 2.7.x + +Kong adopts a structured versioning approach, which makes a +distinction between "major", "minor", and "patch" versions. The upgrade path +will be different depending on which previous version from which you are migrating. + +If you are migrating from 2.x.x, upgrading into 2.7.x is a +minor upgrade, but read below for important instructions on database migration, +especially for Cassandra users. + +If you are migrating from 1.x, upgrading into 2.7.x is a major upgrade, +so, in addition, be aware of any [breaking changes](https://github.com/Kong/kong/blob/master/UPGRADE.md#breaking-changes-2.0) +between the 1.x and 2.x series below, further detailed in the +[CHANGELOG.md](https://github.com/Kong/kong/blob/2.0.0/CHANGELOG.md#200) document. + + +### Dependencies + +If you are using the provided binary packages, all necessary dependencies +for the gateway are bundled and you can skip this section. + +If you are building your dependencies by hand, there are changes since the +previous release, so you will need to rebuild them with the latest patches. + +The required OpenResty version for kong 2.7.x is +[1.19.9.1](https://openresty.org/en/changelog-1019003.html). This is more recent +than the version in Kong 2.5.0 (which used `1.19.3.2`). In addition to an upgraded +OpenResty, you will need the correct [OpenResty patches](https://github.com/Kong/kong-build-tools/tree/master/openresty-patches) +for this new version, including the latest release of [lua-kong-nginx-module](https://github.com/Kong/lua-kong-nginx-module). +The [kong-build-tools](https://github.com/Kong/kong-build-tools) +repository contains [openresty-build-tools](https://github.com/Kong/kong-build-tools/tree/master/openresty-build-tools), +which allows you to more easily build OpenResty with the necessary patches and modules. + +There is a new way to deploy Go using Plugin Servers. +For more information, see [Developing Go plugins](/gateway/2.6.x/reference/external-plugins/#developing-go-plugins). + +### Template changes + +There are **Changes in the Nginx configuration file**, between kong 2.0.x, +2.1.x, 2.2.x, 2.3.x, 2.4.x, 2.5.x, 2.6.x and 2.7.x + +To view the configuration changes between versions, clone the +[Kong repository](https://github.com/kong/kong) and run `git diff` +on the configuration templates, using `-w` for greater readability. + +Here's how to see the differences between previous versions and 2.7.x: + +``` +git clone https://github.com/kong/kong +cd kong +git diff -w 2.0.0 2.7.0 kong/templates/nginx_kong*.lua +``` + +**Note:** Adjust the starting version number +(2.0.x, 2.1.x, 2.2.x, 2.3.x, 2.4.x, 2.5.x, 2.6.x, 2.7.x) to the version number you are currently using. + +To produce a patch file, use the following command: + +``` +git diff 2.0.0 2.7.0 kong/templates/nginx_kong*.lua > kong_config_changes.diff +``` + +**Note:** Adjust the starting version number +(2.0.x, 2.1.x, 2.2.x, 2.3.x, 2.4.x, 2.5.x, 2.6.x, 2.7.x) to the version number you are currently using. + + +### Suggested upgrade path + +The lowest version that Kong 2.7.x supports migrating from is 1.0.x. +If you are migrating from a version lower than 0.14.1, you need to +migrate to 0.14.1 first. Then, once you are migrating from 0.14.1, +please migrate to 1.5.x first. + +The steps for upgrading from 0.14.1 to 1.5.x are the same as upgrading +from 0.14.1 to Kong 1.0. Please follow the steps described in the +"Migration Steps from 0.14" in the + +[Suggested Upgrade Path for Kong 1.0](https://github.com/Kong/kong/blob/master/UPGRADE.md#kong-1-0-upgrade-path) +with the addition of the `kong migrations migrate-apis` command, +which you can use to migrate legacy `apis` configurations. + +Once you migrated to 1.5.x, you can follow the instructions in the section +below to migrate to 2.7.x. + +### Upgrade from 1.0.x - 2.6.x to 2.7.x + +**PostgreSQL** + +Kong 2.7.x supports a no-downtime migration model. This means that while the +migration is ongoing, you will have two Kong clusters running, sharing the +same database. (This is sometimes called the Blue/Green migration model.) + +The migrations are designed so that the new version of Kong is able to use +the database as it is migrated while the old Kong cluster keeps working until +it is time to decommission it. For this reason, the migration is split into +two steps, performed via commands `kong migrations up` (which does +only non-destructive operations) and `kong migrations finish` (which puts the +database in the final expected state for Kong 2.7.x). + +1. Download 2.7.x, and configure it to point to the same datastore + as your old (1.0 to 2.0) cluster. Run `kong migrations up`. +2. After that finishes running, both the old (2.x.x) and new (2.7.x) + clusters can now run simultaneously. Start provisioning 2.7.x nodes, + but do not use their Admin API yet. If you need to perform Admin API + requests, these should be made to the old cluster's nodes. The reason + is to prevent the new cluster from generating data that is not understood + by the old cluster. +3. Gradually divert traffic away from your old nodes, and into + your 2.7.x cluster. Monitor your traffic to make sure everything + is going smoothly. +4. When your traffic is fully migrated to the 2.7.x cluster, + decommission your old nodes. +5. From your 2.7.x cluster, run: `kong migrations finish`. + From this point on, it will not be possible to start + nodes in the old cluster 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 2.7.x nodes. + +**Cassandra** + +{:.warning .no-icon} +> **Deprecation notice:** +> Cassandra as a backend database for {{site.base_gateway}} is deprecated. This means the feature will eventually be removed. Our target for Cassandra removal is the {{site.base_gateway}} 3.4 release, and some new features might not be supported with Cassandra in the {{site.base_gateway}} 3.0 release. + +Due to internal changes, the table schemas used by Kong 2.7.x on Cassandra +are incompatible with those used by Kong 2.1.x (or lower). Migrating using the usual commands +`kong migrations up` and `kong migrations finish` will require a small +window of downtime, since the old and new versions cannot use the +database at the same time. Alternatively, to keep your previous version fully +operational while the new one initializes, you will need to transfer the +data to a new keyspace via a database dump, as described below: + +1. Download 2.7.x, and configure it to point to a new keyspace. + Run `kong migrations bootstrap`. +2. Once that finishes running, both the old (pre-2.1) and new (2.7.x) + clusters can now run simultaneously, but the new cluster does not + have any data yet. +3. On the old cluster, run `kong config db_export`. This will create + a file `kong.yml` with a database dump. +4. Transfer the file to the new cluster and run + `kong config db_import kong.yml`. This will load the data into the new cluster. +5. Gradually divert traffic away from your old nodes, and into + your 2.7.x cluster. Monitor your traffic to make sure everything + is going smoothly. +6. When your traffic is fully migrated to the 2.7.x cluster, + decommission your old nodes. + +### Installing 2.7.x on a fresh datastore + +The following commands should be used to prepare a new 2.7.x cluster from a +fresh datastore. By default the `kong` CLI tool will load the configuration +from `/etc/kong/kong.conf`, but you can optionally use the flag `-c` to +indicate the path to your configuration file: + +``` +$ kong migrations bootstrap [-c /path/to/your/kong.conf] +$ kong start [-c /path/to/your/kong.conf] +``` +Unless indicated otherwise in one of the upgrade paths of this document, it is +possible to upgrade Kong **without downtime**. + +Assuming that Kong is already running on your system, acquire the latest +version from any of the available [installation methods](/gateway/latest/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](/gateway/2.7.x/reference/cli/#kong-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. diff --git a/app/gateway/2.7.x/pdk/index.md b/app/gateway/2.7.x/pdk/index.md new file mode 100644 index 000000000000..537ad102f268 --- /dev/null +++ b/app/gateway/2.7.x/pdk/index.md @@ -0,0 +1,182 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: PDK +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + +## 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) -- "2.0.0" +``` + +[Back to top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) + + +### 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 top](#plugin-development-kit) diff --git a/app/gateway/2.7.x/pdk/kong.client.md b/app/gateway/2.7.x/pdk/kong.client.md new file mode 100644 index 000000000000..f1af97d033b4 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.client.md @@ -0,0 +1,303 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.client +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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, response, 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 top](#kongclient) + + +### 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](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/configuration/#real_ip_recursive) + + +**Phases** + +* certificate, rewrite, access, header_filter, response, 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.client.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 top](#kongclient) + + +### 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, response, 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 top](#kongclient) + + +### 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](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/configuration/#real_ip_recursive) + +**Phases** + +* certificate, rewrite, access, header_filter, response, 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 top](#kongclient) + + +### kong.client.get_credential() + +Returns the credentials of the currently authenticated consumer. + If not set yet, it returns `nil`. + +**Phases** + +* access, header_filter, response, body_filter, log + +**Returns** + +* `string` 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 top](#kongclient) + + +### kong.client.load_consumer(consumer_id[, search_by_username.]) + +Returns the consumer from the datastore. + Will look up the consumer by id, and optionally will do a second search by name. + +**Phases** + +* access, header_filter, response, body_filter, log + +**Parameters** + +* **consumer_id** (string): The consumer id to look up. +* **search_by_username.** (boolean, _optional_): If truthy, + then if the consumer was not found by id, + then a second search by username will be performed + +**Returns** + +1. `table|nil` consumer entity or nil + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +local consumer_id = "john_doe" +local consumer = kong.client.load_consumer(consumer_id, true) +``` + +[Back to top](#kongclient) + + +### kong.client.get_consumer() + +Returns the `consumer` entity of the currently authenticated consumer. + If not set yet, it returns `nil`. + +**Phases** + +* access, header_filter, response, 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 top](#kongclient) + + +### 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 top](#kongclient) + + +### kong.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, response, body_filter, log + +**Parameters** + +* **allow_terminated.** (boolean, _optional_): If set, the `X-Forwarded-Proto` header will be checked when checking for https + +**Returns** + +1. `string|nil` `"http"`, `"https"`, `"tcp"`, `"tls"` or `nil` + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +kong.client.get_protocol() -- "http" +``` + +[Back to top](#kongclient) diff --git a/app/gateway/2.7.x/pdk/kong.client.tls.md b/app/gateway/2.7.x/pdk/kong.client.tls.md new file mode 100644 index 000000000000..befa7295ec59 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.client.tls.md @@ -0,0 +1,148 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.client.tls +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## kong.client.tls + +The client.tls module provides functions for interacting with TLS + connections from client. + + + +### kong.client.tls.request_client_certificate() + +Requests client to present its client-side certificate to initiate mutual + TLS authentication between server and client. + + This function only *requests*, but does not *require* the client to start + the mTLS process. Even if the client did not present a client certificate + the TLS handshake will still complete (obviously not being mTLS in that + case). Whether the client honored the request can be determined using + get_full_client_certificate_chain in later phases. + + +**Phases** + +* certificate + +**Returns** + +1. `true|nil` true if request was received, nil if request failed + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +local res, err = kong.client.tls.request_client_certificate() +if not res then + -- do something with err +end +``` + +[Back to top](#kongclienttls) + + +### kong.client.tls.disable_session_reuse() + +Prevents the TLS session for the current connection from being reused + by disabling session ticket and session ID for the current TLS connection. + +**Phases** + +* certificate + +**Returns** + +1. `true|nil` true if success, nil if failed + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +local res, err = kong.client.tls.disable_session_reuse() +if not res then + -- do something with err +end +``` + +[Back to top](#kongclienttls) + + +### kong.client.tls.get_full_client_certificate_chain() + +Returns the PEM encoded downstream client certificate chain with the + client certificate at the top and intermediate certificates + (if any) at the bottom. + +**Phases** + +* rewrite, access, balancer, header_filter, body_filter, log + +**Returns** + +1. `string|nil` PEM-encoded client certificate if mTLS handshake + was completed, nil if an error occurred or client did not present + its certificate + +1. `nil|err` nil if success, or error message if failure + + +**Usage** + +``` lua +local cert, err = kong.client.get_full_client_certificate_chain() +if err then + -- do something with err +end + +if not cert then + -- client did not complete mTLS +end + +-- do something with cert +``` + +[Back to top](#kongclienttls) + + +### kong.client.tls.set_client_verify() + +Overrides client verify result generated by the log serializer. + + By default, the `request.tls.client_verify` field inside the log + generated by Kong's log serializer is the same as the + [$ssl_client_verify](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_client_verify) + Nginx variable. + + Only "SUCCESS", "NONE" or "FAILED:" are accepted values. + + This function does not return anything on success, and throws an Lua error + in case of failures. + + +**Phases** + +* rewrite, access, balancer + +**Usage** + +``` lua +kong.client.tls.set_client_verify("FAILED:unknown CA") +``` + +[Back to top](#kongclienttls) diff --git a/app/gateway/2.7.x/pdk/kong.cluster.md b/app/gateway/2.7.x/pdk/kong.cluster.md new file mode 100644 index 000000000000..43493f8ab7b3 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.cluster.md @@ -0,0 +1,56 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.cluster +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## kong.cluster + +Cluster-level utilities + + + +### kong.cluster.get_id() + +Returns the unique id for this Kong cluster. If Kong + is running in DB-less mode without a cluster ID explicitly defined, + then this method returns nil. + + For Hybrid mode, all Control Planes and Data Planes belonging to the same + cluster returns the same cluster ID. For traditional database based + deployments, all Kong nodes pointing to the same database will also return + the same cluster ID. + + +**Returns** + +1. `string|nil` The v4 UUID used by this cluster as its id + +1. `string|nil` an error message + + +**Usage** + +``` lua +local id, err = kong.cluster.get_id() +if err then + -- handle error +end + +if not id then + -- no cluster ID is available +end + +-- use id here +``` + +[Back to top](#kongcluster) diff --git a/app/gateway/2.7.x/pdk/kong.ctx.md b/app/gateway/2.7.x/pdk/kong.ctx.md new file mode 100644 index 000000000000..ad17f5903db3 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.ctx.md @@ -0,0 +1,115 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.ctx +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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`, `response`, `body_filter`, `log`, and `preread` 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, response, body_filter, log, preread + +**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 top](#kongctx) + + +### 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 overwriting 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`, `log`, and `preread` 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, response, body_filter, log, preread + +**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 top](#kongctx) diff --git a/app/gateway/2.7.x/pdk/kong.ip.md b/app/gateway/2.7.x/pdk/kong.ip.md new file mode 100644 index 000000000000..4a67218de322 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.ip.md @@ -0,0 +1,59 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.ip +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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](/gateway/latest/reference/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, response, 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 top](#kongip) diff --git a/app/gateway/2.7.x/pdk/kong.log.md b/app/gateway/2.7.x/pdk/kong.log.md new file mode 100644 index 000000000000..37f464b63e43 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.log.md @@ -0,0 +1,465 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.log +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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: + + ```plaintext + [kong] %file_src:%line_src %message + ``` + + In comparison, log lines produced by plugins have the following format: + + ```plaintext + [kong] %file_src:%line_src [%namespace] %message + ``` + + Where: + + * `%namespace`: is the configured namespace (the plugin name in this case). + * `%file_src`: is the filename 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: + + ```plaintext + 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: + + ```plaintext + 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, response, 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 top](#konglog) + + +### 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: + + ```plaintext + 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: + + ```plaintext + 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, response, 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 top](#konglog) + + +### kong.log.deprecation(...) + +Write a deprecation log line (similar to `kong.log.warn`). + + 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). When the last argument is a table, + it is considered as a deprecation metadata. The table can include following + properties: + + ``` lua + { + after = "2.5.0", -- deprecated after Kong version 2.5.0 (defaults to `nil`) + removal = "3.0.0", -- about to be removed with Kong version 3.0.0 (defaults to `nil`) + trace = true, -- writes stack trace along with the deprecation message (defaults to `nil`) + } + ``` + + For example, the following call: + + ``` lua + kong.log.deprecation("hello ", "world") + ``` + + would, within the core, produce a log line similar to: + + ```plaintext + 2017/07/09 19:36:25 [warn] 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: + + ```plaintext + 2017/07/09 19:36:25 [warn] 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" + ``` + + And with metatable, the following call: + + ``` lua + kong.log.deprecation("hello ", "world", { after = "2.5.0", removal = "3.0.0" }) + ``` + + would, within the core, produce a log line similar to: + + ```plaintext + 2017/07/09 19:36:25 [warn] 25932#0: *1 [kong] some_file.lua:54 hello world (deprecated after 2.5.0, scheduled for removal in 3.0.0), client: 127.0.0.1, server: localhost, request: "GET /log HTTP/1.1", host: "localhost" + ``` + + +**Phases** + +* init_worker, certificate, rewrite, access, header_filter, response, body_filter, log + +**Parameters** + +* **...** : all params will be concatenated and stringified before being sent to the log + (if the last param is a table, it is considered as a deprecation metadata) + +**Returns** + +* Nothing; throws an error on invalid inputs. + + +**Usage** + +``` lua +kong.log.deprecation("hello ", "world") +kong.log.deprecation("hello ", "world", { after = "2.5.0" }) +kong.log.deprecation("hello ", "world", { removal = "3.0.0" }) +kong.log.deprecation("hello ", "world", { after = "2.5.0", removal = "3.0.0" }) +kong.log.deprecation("hello ", "world", { trace = true }) +``` + +[Back to top](#konglog) + + +### 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. + + 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: + + ```plaintext + %file_src:%func_name:%line_src %message + ``` + + Where: + + * `%file_src`: is the filename 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, response, 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 top](#konglog) + + +### 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, response, body_filter, log + +**Usage** + +``` lua +kong.log.inspect.on() +``` + +[Back to top](#konglog) + + +### 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, response, body_filter, log + +**Usage** + +``` lua +kong.log.inspect.off() +``` + +[Back to top](#konglog) + + +### kong.log.set_serialize_value(key, value, options) + +Sets a value to be used on the `serialize` custom table + + Logging plugins use the output of `kong.log.serialize()` as a base for their logs. + + This function allows customizing such output. + + It can be used to replace existing values on the output. + It can be used to delete existing values by passing `nil`. + + Note: the type checking of the `value` parameter can take some time so + it is deferred to the `serialize()` call, which happens in the log + phase in most real-usage cases. + + +**Phases** + +* certificate, rewrite, access, header_filter, response, body_filter, log + +**Parameters** + +* **key** (string): the name of the field. +* **value** (number|string|boolean|table): value to be set. When a table is used, its keys must be numbers, strings, booleans, and its values can be numbers, strings or other tables like itself, recursively. +* **options** (table): can contain two entries: options.mode can be `set` (the default, always sets), `add` (only add if entry does not already exist) and `replace` (only change value if it already exists). + +**Returns** + +* `table` the request information table + + +**Usage** + +``` lua +-- Adds a new value to the serialized table +kong.log.set_serialize_value("my_new_value", 1) +assert(kong.log.serialize().my_new_value == 1) + +-- Value can be a table +kong.log.set_serialize_value("my", { new = { value = 2 } }) +assert(kong.log.serialize().my.new.value == 2) + +-- It is possible to change an existing serialized value +kong.log.set_serialize_value("my_new_value", 3) +assert(kong.log.serialize().my_new_value == 3) + +-- Unset an existing value by setting it to nil +kong.log.set_serialize_value("my_new_value", nil) +assert(kong.log.serialize().my_new_value == nil) + +-- Dots in the key are interpreted as table accesses +kong.log.set_serialize_value("my.new.value", 4) +assert(kong.log.serialize().my.new_value == 4) +``` + +[Back to top](#konglog) + + +### kong.log.serialize() + +Generates a table that contains information that are helpful for logging. + + This method can currently be used in the `http` subsystem. + + The following fields are included in the returned table: + * `client_ip` - client IP address in textual format. + * `latencies` - request/proxy latencies. + * `request.headers` - request headers. + * `request.method` - request method. + * `request.querystring` - request query strings. + * `request.size` - size of request. + * `request.url` and `request.uri` - URL and URI of request. + * `response.headers` - response headers. + * `response.size` - size of response. + * `response.status` - response HTTP status code. + * `route` - route object matched. + * `service` - service object used. + * `started_at` - timestamp this request came in, in milliseconds. + * `tries` - Upstream information; this is an array and if any balancer retries occurred, will contain more than one entry. + * `upstream_uri` - request URI sent to Upstream. + + The following fields are only present in an authenticated request (with consumer): + + * `authenticated_entity` - credential used for authentication. + * `consumer` - consumer entity accessing the resource. + + The following fields are only present in a TLS/HTTPS request: + * `request.tls.version` - TLS/SSL version used by the connection. + * `request.tls.cipher` - TLS/SSL cipher used by the connection. + * `request.tls.client_verify` - mTLS validation result. Contents are the same as described in [$ssl_client_verify](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#var_ssl_client_verify). + + **Warning:** This function may return sensitive data (e.g., API keys). + Consider filtering before writing it to unsecured locations. + + All fields in the returned table may be altered via kong.log.set_serialize_value + + The following http authentication headers are redacted by default, if they appear in the request: + * `request.headers.authorization` + * `request.headers.proxy-authorization` + + To see what content is present in your setup, enable any of the logging + plugins (e.g., `file-log`) and the output written to the log file is the table + returned by this function JSON-encoded. + + +**Phases** + +* log + +**Returns** + +* `table` the request information table + + +**Usage** + +``` lua +kong.log.serialize() +``` + +[Back to top](#konglog) diff --git a/app/gateway/2.7.x/pdk/kong.nginx.md b/app/gateway/2.7.x/pdk/kong.nginx.md new file mode 100644 index 000000000000..b0e481fdf14d --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.nginx.md @@ -0,0 +1,44 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.nginx +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## kong.nginx + +Nginx information module + A set of functions allowing to retrieve Nginx-specific implementation + details and meta information. + + + +### kong.nginx.get_subsystem() + +Returns the current Nginx subsystem this function is called from: "http" + or "stream". + +**Phases** + +* any + +**Returns** + +* `string` subsystem Either `"http"` or `"stream"` + + +**Usage** + +``` lua +kong.nginx.get_subsystem() -- "http" +``` + +[Back to top](#kongnginx) diff --git a/app/gateway/2.7.x/pdk/kong.node.md b/app/gateway/2.7.x/pdk/kong.node.md new file mode 100644 index 000000000000..a3586ff5c605 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.node.md @@ -0,0 +1,131 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.node +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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 top](#kongnode) + + +### kong.node.get_memory_stats([unit[, scale]]) + +Returns memory usage statistics about this node. + +**Parameters** + +* **unit** (string, _optional_): The unit memory should be reported in. Can be + either of `b/B`, `k/K`, `m/M`, or `g/G` for bytes, kibibytes, mebibytes, + or gibibytes, respectively. Defaults to `b` (bytes). +* **scale** (number, _optional_): The number of digits to the right of the decimal + point. Defaults to 2. + +**Returns** + +* `table` A table containing memory usage statistics for this node. + If `unit` is `b/B` (the default) reported values will be Lua numbers. + Otherwise, reported values will be a string with the unit as a suffix. + + +**Usage** + +``` lua +local res = kong.node.get_memory_stats() +-- res will have the following structure: +{ + lua_shared_dicts = { + kong = { + allocated_slabs = 12288, + capacity = 24576 + }, + kong_db_cache = { + allocated_slabs = 12288, + capacity = 12288 + } + }, + workers_lua_vms = { + { + http_allocated_gc = 1102, + pid = 18004 + }, + { + http_allocated_gc = 1102, + pid = 18005 + } + } +} + +local res = kong.node.get_memory_stats("k", 1) +-- res will have the following structure: +{ + lua_shared_dicts = { + kong = { + allocated_slabs = "12.0 KiB", + capacity = "24.0 KiB", + }, + kong_db_cache = { + allocated_slabs = "12.0 KiB", + capacity = "12.0 KiB", + } + }, + workers_lua_vms = { + { + http_allocated_gc = "1.1 KiB", + pid = 18004 + }, + { + http_allocated_gc = "1.1 KiB", + pid = 18005 + } + } +} +``` + +[Back to top](#kongnode) + + +### kong.node.get_hostname() + +Returns the name used by the local machine + +**Returns** + +* `string` The local machine hostname + + +**Usage** + +``` lua +local hostname = kong.node.get_hostname() +``` + +[Back to top](#kongnode) diff --git a/app/gateway/2.7.x/pdk/kong.request.md b/app/gateway/2.7.x/pdk/kong.request.md new file mode 100644 index 000000000000..c4e29eb14178 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.request.md @@ -0,0 +1,688 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.request +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/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, response, body_filter, log, admin_api + +**Returns** + +* `string` the forwarded scheme + + +**Usage** + +``` lua +kong.request.get_forwarded_scheme() -- "https" +``` + +[Back to top](#kongrequest) + + +### 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-Host` or not depends on + several Kong configuration parameters: + + * [trusted\_ips](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/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, response, body_filter, log, admin_api + +**Returns** + +* `string` the forwarded host + + +**Usage** + +``` lua +kong.request.get_forwarded_host() -- "example.com" +``` + +[Back to top](#kongrequest) + + +### kong.request.get_forwarded_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](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/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. + + When running Kong behind the L4 port mapping (or forwarding) you can also + configure: + * [port\_maps](/gateway/latest/reference/configuration/#port_maps) + + `port_maps` configuration parameter enables this function to return the + port to which the port Kong is listening to is mapped to (in case they differ). + + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `number` the forwarded port + + +**Usage** + +``` lua +kong.request.get_forwarded_port() -- 1234 +``` + +[Back to top](#kongrequest) + + +### kong.request.get_forwarded_path() + +Returns the path component of the request's URL, but also considers + `X-Forwarded-Path` if it comes from a trusted source. The value + is returned as a Lua string. + + Whether this function considers `X-Forwarded-Path` or not depends on + several Kong configuration parameters: + + * [trusted\_ips](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/configuration/#real_ip_recursive) + + **Note**: we do not currently do any normalization on the request path. + + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `string` the forwarded path + + +**Usage** + +``` lua +kong.request.get_forwarded_path() -- /path +``` + +[Back to top](#kongrequest) + + +### kong.request.get_forwarded_prefix() + +Returns the prefix path component of the request's URL that Kong stripped + before proxying to upstream. It also checks if `X-Forwarded-Prefix` comes + from a trusted source, and uses it as is when given. The value is returned + as a Lua string. + + If a trusted `X-Forwarded-Prefix` is not passed, this function must be called after Kong has ran its router (`access` phase), + as the Kong router may strip the prefix of the request path. That stripped + path will become the return value of this function, unless there was already + a trusted `X-Forwarded-Prefix` header in the request. + + Whether this function considers `X-Forwarded-Prefix` or not depends on + several Kong configuration parameters: + + * [trusted\_ips](/gateway/latest/reference/configuration/#trusted_ips) + * [real\_ip\_header](/gateway/latest/reference/configuration/#real_ip_header) + * [real\_ip\_recursive](/gateway/latest/reference/configuration/#real_ip_recursive) + + **Note**: we do not currently do any normalization on the request path prefix. + + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `string|nil` the forwarded path prefix or nil if prefix was not stripped + + +**Usage** + +``` lua +kong.request.get_forwarded_prefix() -- /prefix +``` + +[Back to top](#kongrequest) + + +### kong.request.get_http_version() + +Returns the HTTP version used by the client in the request as a Lua + number, returning values such as `1`, `1.1`, `2.0`, or `nil` for + unrecognized values. + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `number|nil` the HTTP version as a Lua number + + +**Usage** + +``` lua +kong.request.get_http_version() -- 1.1 +``` + +[Back to top](#kongrequest) + + +### kong.request.get_method() + +Returns the HTTP method of the request. The value is normalized to + upper-case. + + +**Phases** + +* rewrite, access, header_filter, response, body_filter, log, admin_api + +**Returns** + +* `string` the request method + + +**Usage** + +``` lua +kong.request.get_method() -- "GET" +``` + +[Back to top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### kong.request.get_path_with_query() + +Returns the path, including the querystring if any. No + transformations/normalizations are done. + + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) + + +### 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, response, 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 top](#kongrequest) diff --git a/app/gateway/2.7.x/pdk/kong.response.md b/app/gateway/2.7.x/pdk/kong.response.md new file mode 100644 index 000000000000..c808e7c7334d --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.response.md @@ -0,0 +1,639 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.response +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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, response, 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 top](#kongresponse) + + +### 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, response, 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 top](#kongresponse) + + +### 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, response, 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 top](#kongresponse) + + +### 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, response, 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 top](#kongresponse) + + +### kong.response.set_status(status) + +Allows changing the downstream response HTTP status code before sending it + to the client. + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongresponse) + + +### kong.response.set_header(name, value) + +Sets a response header with the given value. This function overrides any + existing header with the same name. + + Note: Underscores in Header names are automatically transformed into dashes + by default. If you want to deactivate this behavior you should set + the `lua_transform_underscores_in_response_headers` nginx config option to `off` + + This setting can be set in the Kong Config file: + + nginx_http_lua_transform_underscores_in_response_headers = off + + Be aware that changing this setting might slightly break any plugins that + rely on the automatic underscore conversion. + + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongresponse) + + +### 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().` + + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongresponse) + + +### kong.response.clear_header(name) + +Removes all occurrences of the specified header in the response sent to + the client. + +**Phases** + +* rewrite, access, header_filter, response, 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 top](#kongresponse) + + +### 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. + + 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, response, 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 top](#kongresponse) + + +### kong.response.get_raw_body() + +Returns the full body when the last chunk has been read. + + Calling this function will start to buffer the body in + an internal request context variable, and set the current + chunk (`ngx.arg[1]`) to `nil` when the chunk is not the + last one. Otherwise it returns the full buffered body. + + +**Phases** + +* `body_filter` + +**Returns** + +* `string` body The full body when the last chunk has been read, + otherwise returns `nil` + + +**Usage** + +``` lua +local body = kong.response.get_raw_body() +if body then + body = transform(body) + kong.response.set_raw_body(body) +end +``` + +[Back to top](#kongresponse) + + +### kong.response.set_raw_body(body) + +Sets the body of the response + + The `body` argument must be a string and will not be processed in any way. + This function cannot anymore change the `Content-Length` header if one was + added. So if you decide to use this function, the `Content-Length` header + should also be cleared, e.g. in `header_filter` phase. + + +**Phases** + +* `body_filter` + +**Parameters** + +* **body** (string): The raw body + +**Returns** + +* Nothing; throws an error on invalid inputs. + + +**Usage** + +``` lua +kong.response.set_raw_body("Hello, world!") +-- or +local body = kong.response.get_raw_body() +if body then + body = transform(body) + kong.response.set_raw_body(body) +end +``` + +[Back to top](#kongresponse) + + +### 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. + + **In L4 proxy mode**, **only** the following status code are supported: + + * 200 - OK + * 400 - Bad request + * 403 - Forbidden + * 500 - Internal server error + * 502 - Bad gateway + * 503 - Service unavailable + + For **L4 proxy mode** the `status` code provided is primarily for logging + and statistical purpose, and is not visible to the client directly. + + 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. On gRPC we cannot send + the `body` with this function at the moment at least, so what it does + instead is that it sends "body" in `grpc-message` header instead. If the + body is a table it looks for a field `message` in it, and uses that as a + `grpc-message` header. Though, if you have specified `Content-Type` header + starting with `application/grpc`, the body will be sent. + + **In L4 proxy mode**, `body` can only be `nil` or a string. Automatic JSON + encoding is not available. When provided, depends on the value of `status`, + the following will happen: + + When `status` is 500, 502 or 503, then `body` will be logged in the Kong + error log file. Otherwise `body` will be sent back to the L4 client. + + 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()`. This argument is ignored in L4 proxy mode. + + Unless manually specified, this method will automatically set the + Content-Length header in the produced response for convenience. + +**Phases** + +* preread, 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" +}) + +--- + +-- In L4 proxy mode +return kong.response.exit(200, "Success") +``` + +[Back to top](#kongresponse) + + +### kong.response.error(status[, message[, headers]]) + +This function interrupts the current processing and produces an error + response. + + It is recommended to use this function in conjunction with the `return` + operator, to better reflect its meaning: + + ```lua + return kong.response.error(500, "Error", {["Content-Type"] = "text/html"}) + ``` + + The first argument `status` will set the status code of the response that + will be seen by the client. The status code must be of an error, i.e. + >399. + + The second, optional, `message` argument will set the message describing + the error, which will be written in the body. + + 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()`. + + This method will send the response formatted in JSON, XML, HTML or plain + text. The actual format is chosen using one of the following options: + - Manually specifying in `headers` argument using the `Content-Type` + header. + - Conform to the `Accept` header from the request. + - If none of the above is found, fallback to JSON format. + 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 (>399) +* **message** (string, _optional_): The error message to be used +* **headers** (table, _optional_): The headers to be used + +**Returns** + +* Nothing; throws an error on invalid input. + + +**Usage** + +``` lua +return kong.response.error(403, "Access Forbidden", { + ["Content-Type"] = "text/plain", + ["WWW-Authenticate"] = "Basic" +}) + +--- + +return kong.response.error(403, "Access Forbidden") + +--- + +return kong.response.error(403) +``` + +[Back to top](#kongresponse) diff --git a/app/gateway/2.7.x/pdk/kong.router.md b/app/gateway/2.7.x/pdk/kong.router.md new file mode 100644 index 000000000000..66b0bae6b63c --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.router.md @@ -0,0 +1,73 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.router +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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, response, body_filter, log + +**Returns** + +* `table` the `route` entity. + + +**Usage** + +``` lua +local route = kong.router.get_route() +local protocols = route.protocols +``` + +[Back to top](#kongrouter) + + +### kong.router.get_service() + +Returns the current `service` entity. The request will be targeted to this + upstream service. + + +**Phases** + +* access, header_filter, response, 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 route without a service +end +``` + +[Back to top](#kongrouter) diff --git a/app/gateway/2.7.x/pdk/kong.service.md b/app/gateway/2.7.x/pdk/kong.service.md new file mode 100644 index 000000000000..b140c6297628 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.service.md @@ -0,0 +1,258 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.service +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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 + health checking. + + + +### 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 top](#kongservice) + + +### 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 top](#kongservice) + + +### kong.service.set_tls_cert_key(chain, key) + +Sets the client certificate used while handshaking with the Service. + + The `chain` argument is the client certificate and intermediate chain (if any) + returned by functions such as [ngx.ssl.parse\_pem\_cert](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_cert). + + The `key` argument is the private key corresponding to the client certificate + returned by functions such as [ngx.ssl.parse\_pem\_priv\_key](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/ssl.md#parse_pem_priv_key). + + +**Phases** + +* `rewrite`, `access`, `balancer` + +**Parameters** + +* **chain** (cdata): The client certificate chain +* **key** (cdata): The client certificate private key + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one + + +**Usage** + +``` lua +local chain = assert(ssl.parse_pem_cert(cert_data)) +local key = assert(ssl.parse_pem_priv_key(key_data)) + +local ok, err = kong.service.set_tls_cert_key(chain, key) +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservice) + + +### kong.service.set_tls_verify(on) + +Sets whether TLS verification is enabled while handshaking with the Service. + + The `on` argument is a boolean flag, where `true` means upstream verification + is enabled and `false` disables it. + + This call affects only the current request. If the trusted certificate store is + not set already (via [proxy_ssl_trusted_certificate](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_trusted_certificate) + or [kong.service.set_upstream_ssl_trusted_store](#kongserviceset_upstream_ssl_trusted_store)), + then TLS verification will always fail with "unable to get local issuer certificate" error. + + +**Phases** + +* `rewrite`, `access`, `balancer` + +**Parameters** + +* **on** (boolean): Whether to enable TLS certificate verification for the current request + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one + + +**Usage** + +``` lua +local ok, err = kong.service.set_tls_verify(true) +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservice) + + +### kong.service.set_tls_verify_depth(depth) + +Sets the maximum depth of verification when validating upstream server's TLS certificate. + + This call affects only the current request. For the depth to be actually used the verification + has to be enabled with either the [proxy_ssl_verify](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_verify) + directive or using the [kong.service.set_tls_verify](#kongserviceset_tls_verify) function. + + +**Phases** + +* `rewrite`, `access`, `balancer` + +**Parameters** + +* **depth** (number): Depth to use when validating. Must be non-negative + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one + + +**Usage** + +``` lua +local ok, err = kong.service.set_tls_verify_depth(3) +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservice) + + +### kong.service.set_tls_verify_store(store) + +Sets the CA trust store to use when validating upstream server's TLS certificate. + + This call affects only the current request. For the store to be actually used the verification + has to be enabled with either the [proxy_ssl_verify](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_verify) + directive or using the [kong.service.set_tls_verify](#kongserviceset_tls_verify) function. + + The resty.openssl.x509.store object can be created by following + [examples](https://github.com/Kong/lua-kong-nginx-module#restykongtlsset_upstream_ssl_trusted_store) from the Kong/lua-kong-nginx-module repo. + + +**Phases** + +* `rewrite`, `access`, `balancer` + +**Parameters** + +* **store** (table): resty.openssl.x509.store object to use + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one + + +**Usage** + +``` lua +local store = require("resty.openssl.x509.store") +local st = assert(store.new()) +-- st:add(...certificate) + +local ok, err = kong.service.set_tls_verify_store(st) +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservice) diff --git a/app/gateway/2.7.x/pdk/kong.service.request.md b/app/gateway/2.7.x/pdk/kong.service.request.md new file mode 100644 index 000000000000..786f4a516892 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.service.request.md @@ -0,0 +1,505 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.service.request +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## kong.service.request + +Manipulation of the request to the Service + + + +### kong.service.request.enable_buffering() + +Enables buffered proxying that allows plugins to access service body and + response headers at the same time + +**Phases** + +* `rewrite`, `access` + +**Returns** + +* Nothing + + +**Usage** + +``` lua +kong.service.request.enable_buffering() +``` + +[Back to top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### kong.service.request.set_path(path) + +Sets the path component for the request to the service. + + The input accepts any valid *normalized* URI (including UTF-8 characters) + and this API will perform necessary escaping according to the RFC + to make the request valid. + + Input should **not** include the querystring. + +**Phases** + +* `access` + +**Parameters** + +* **path** (string): The path string. Special characters and UTF-8 characters are allowed. Example: "/v2/movies" or "/foo/😀" + +**Returns** + +* Nothing; throws an error on invalid inputs. + + +**Usage** + +``` lua +kong.service.request.set_path("/v2/movies") +``` + +[Back to top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### kong.service.request.set_method(method) + +Sets the HTTP method for the request to the service. + +**Phases** + +* `rewrite`, `access` + +**Parameters** + +* **method** (string): 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### 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`, `balancer` + +**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 top](#kongservicerequest) + + +### 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 occurrences 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### 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 top](#kongservicerequest) + + +### kong.service.request.disable_tls() + +Disables the TLS handshake to upstream for [ngx\_stream\_proxy\_module](https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html). + Effectively this overrides [proxy\_ssl](https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_ssl) directive to `off` setting + for the current stream session. + + Note that once this function has been called it is not possible to re-enable TLS handshake for the current session. + + +**Phases** + +* `preread`, `balancer` + +**Returns** + +1. `boolean|nil` `true` if the operation succeeded, `nil` if an error occurred + +1. `string|nil` An error message describing the error if there was one. + + +**Usage** + +``` lua +local ok, err = kong.service.request.disable_tls() +if not ok then + -- do something with error +end +``` + +[Back to top](#kongservicerequest) diff --git a/app/gateway/2.7.x/pdk/kong.service.response.md b/app/gateway/2.7.x/pdk/kong.service.response.md new file mode 100644 index 000000000000..2bfeeca9a96d --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.service.response.md @@ -0,0 +1,195 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.service.response +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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 top](#kongserviceresponse) + + +### 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 top](#kongserviceresponse) + + +### 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 top](#kongserviceresponse) + + +### kong.service.response.get_raw_body() + +Returns the raw buffered body. + +**Phases** + +* `header_filter`, `body_filter`, `log` + +**Returns** + +* `string` body The raw buffered body + + +**Usage** + +``` lua +-- Plugin needs to call kong.service.request.enable_buffering() on `rewrite` +-- or `access` phase prior calling this function. + +local body = kong.service.response.get_raw_body() +``` + +[Back to top](#kongserviceresponse) + + +### kong.service.response.get_body([mimetype[, max_args]]) + +Returns the decoded buffered body. + +**Phases** + +* `header_filter`, `body_filter`, `log` + +**Parameters** + +* **mimetype** (string, _optional_): The mime-type of the response (if known) +* **max_args** (number, _optional_): set a limit on the maximum number of parsed + +**Returns** + +* `string` body The raw buffered body + + +**Usage** + +``` lua +-- Plugin needs to call kong.service.request.enable_buffering() on `rewrite` +-- or `access` phase prior calling this function. + +local body = kong.service.response.get_body() +``` + +[Back to top](#kongserviceresponse) diff --git a/app/gateway/2.7.x/pdk/kong.table.md b/app/gateway/2.7.x/pdk/kong.table.md new file mode 100644 index 000000000000..360ddcb22ba0 --- /dev/null +++ b/app/gateway/2.7.x/pdk/kong.table.md @@ -0,0 +1,103 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# https://github.com/Kong/kong/tree/master/kong/pdk +# or its associated files +# +title: kong.table +pdk: true +toc: true +source_url: https://github.com/Kong/kong/tree/master/kong/pdk +--- + + + +## 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 top](#kongtable) + + +### 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 top](#kongtable) + + +### kong.table.merge([t1[, t2]]) + +Merges the contents of two tables together, producing a new one. + The entries of both tables are copied non-recursively to the new one. + If both tables have the same key, the second one takes precedence. + If only one table is given, it returns a copy. + +**Parameters** + +* **t1** (table, _optional_): The first table +* **t2** (table, _optional_): The second table + +**Returns** + +* `table` The (new) merged table + + +**Usage** + +``` lua +local t1 = {1, 2, 3, foo = "f"} +local t2 = {4, 5, bar = "b"} +local t3 = kong.table.merge(t1, t2) -- {4, 5, 3, foo = "f", bar = "b"} +``` + +[Back to top](#kongtable) diff --git a/app/gateway/2.7.x/plan-and-deploy/default-ports.md b/app/gateway/2.7.x/plan-and-deploy/default-ports.md new file mode 100644 index 000000000000..c9c8f5959efe --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/default-ports.md @@ -0,0 +1,23 @@ +--- +title: Default Ports +--- +By default, {{site.base_gateway}} listens on the following ports: + +| Port | Protocol | Description | Gateway tier | +|:-----------------------------------------------------------------------------------|:---------|:------------|:----------------------| +| [`:8000`](/gateway/{{page.release}}/reference/configuration/#proxy_listen) | HTTP | Takes incoming HTTP traffic from **Consumers**, and forwards it to upstream **Services**. | All tiers and modes | +| [`:8443`](/gateway/{{page.release}}/reference/configuration/#proxy_listen) | HTTPS | Takes incoming HTTPS traffic from **Consumers**, and forwards it to upstream **Services**. | All tiers and modes | +| [`:8001`](/gateway/{{page.release}}/reference/configuration/#admin_api_uri) | HTTP | Admin API. Listens for calls from the command line over HTTP. | All tiers and modes | +| [`:8444`](/gateway/{{page.release}}/reference/configuration/#admin_api_uri) | HTTPS | Admin API. Listens for calls from the command line over HTTPS. | All tiers and modes | +| [`:8005`](/gateway/{{page.release}}/plan-and-deploy/hybrid-mode/hybrid-mode-setup/) | HTTP | Hybrid mode only. Control Plane listens for traffic from Data Planes. | All tiers and modes | +| [`:8006`](/gateway/{{page.release}}/plan-and-deploy/hybrid-mode/hybrid-mode-setup/) | HTTP | Hybrid mode only. Control Plane listens for Vitals telemetry data from Data Planes. | {{site.ee_product_name}} tier | +| [`:8002`](/gateway/{{page.release}}/reference/configuration/#admin_gui_listen) | HTTP | Kong Manager (GUI). Listens for HTTP traffic. | {{site.base_gateway}} free mode | +| [`:8445`](/gateway/{{page.release}}/reference/configuration/#admin_gui_listen) | HTTPS | Kong Manager (GUI). Listens for HTTPS traffic. | {{site.base_gateway}} free mode | +| [`:8003`](/gateway/{{page.release}}/reference/configuration/#portal_gui_listen) | HTTP | Dev Portal. Listens for HTTP traffic, assuming Dev Portal is **enabled**. | {{site.ee_product_name}} tier | +| [`:8446`](/gateway/{{page.release}}/reference/configuration/#portal_gui_listen) | HTTPS | Dev Portal. Listens for HTTPS traffic, assuming Dev Portal is **enabled**. | {{site.ee_product_name}} tier | +| [`:8004`](/gateway/{{page.release}}/reference/configuration/#portal_api_listen) | HTTP | Dev Portal `/files` traffic over HTTP, assuming the Dev Portal is **enabled**. | {{site.ee_product_name}} tier | +| [`:8447`](/gateway/{{page.release}}/reference/configuration/#portal_api_listen) | HTTPS | Dev Portal `/files` traffic over HTTPS, assuming the Dev Portal is **enabled**. | {{site.ee_product_name}} tier | + +{:.note} +> **Note:** {{site.base_gateway}} free mode and Enterprise tier are not available for +open-source Gateway packages. diff --git a/app/gateway/2.7.x/plan-and-deploy/dns-considerations.md b/app/gateway/2.7.x/plan-and-deploy/dns-considerations.md new file mode 100644 index 000000000000..b4f1607037eb --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/dns-considerations.md @@ -0,0 +1,257 @@ +--- +title: DNS Considerations for Kong Gateway +badge: enterprise +--- + +{{site.base_gateway}} provides web applications that must be able to interact with +other Kong services to function properly: Kong Manager must be able to +interact with the Admin API, and the Dev Portal must be able to interact with +the Portal API. These applications are subject to security restrictions +enforced by browsers, and Kong must send appropriate information to browsers in +order for them to function properly. + +These security restrictions use the applications' DNS hostnames to evaluate +whether the applications' metadata satisfies the security constraints. As such, +you must design your DNS structure to meet the requirements. + +## Quick guide + +It is recommended you read through this document to understand why these +requirements exist and how they function. In brief, your environment must meet +one of the two criteria below: + +* Kong Manager and the Admin API are served from the same hostname, typically + by placing the Admin API under an otherwise unused path, such as `/_adminapi/`. +* Kong Manager and the Admin API are served from different hostnames with a + shared suffix (e.g. `kong.example` for `api.admin.kong.example` and + `manager.admin.kong.example`). Admin session configuration sets + `cookie_domain` to the shared suffix. + +The same applies to the Portal API and Dev Portal. + +The first option simplifies configuration in `kong.conf`, but requires an HTTP +proxy in front of the applications (because it uses HTTP path-based routing). +The Kong proxy can be used for this. The second option requires more +configuration in kong.conf, but can be used without proxying the applications. + +## CORS + +### Understanding CORS + +[Cross-Origin Resource Sharing, or CORS][mdn-cors], is a set of rules for web +applications that make requests across origins, i.e. to URLs that do not share +the same scheme, hostname, and port as the page making the request. When making +a cross-origin request, browsers send an `Origin` request header, and servers +must respond with a matching `Access-Control-Allow-Origin` (ACAO) header. If +the two headers do not match, the browser will discard the response, and any +application components that require that response's data will not function +properly. + +For example, the following request/response pairs have matching CORS headers, +and will succeed: + +``` +GET / HTTP/1.1 +Host: example.com +Origin: http://example.net + +HTTP/1.1 200 OK +Access-Control-Allow-Origin: http://example.net +``` + +``` +GET / HTTP/1.1 +Host: example.com +Origin: http://example.net + +HTTP/1.1 200 OK +Access-Control-Allow-Origin: * +``` + +`*` indicates that any origin is allowed. + +These requests do not have a matching pair of CORS headers, and will fail: + +``` +GET / HTTP/1.1 +Host: example.com +Origin: http://example.net + +HTTP/1.1 200 OK +Access-Control-Allow-Origin: http://badbadcors.example +``` + +``` +GET / HTTP/1.1 +Host: example.com +Origin: http://example.net + +HTTP/1.1 200 OK +``` + +Missing CORS headers when CORS headers are expected results in failure. + +### CORS in the context of {{site.base_gateway}} + +Kong Manager and the Dev Portal operate by issuing requests to their respective +APIs using JavaScript. These requests may be cross-origin depending on your +environment. + +Kong's services determine what CORS headers to send based on various location +hint settings in `kong.conf`. The Admin API obtains its ACAO header value from +`admin_gui_url` and the Portal API obtains its header value from the +information in the `portal_gui_protocol`, `portal_gui_host`, and +`portal_gui_use_subdomains` settings. You may optionally specify additional +Portal API origins using `portal_cors_origins`. + +You can configure your environment such that these requests are not +cross-origin by accessing both the GUI and its associated API via the same +hostname, e.g. by accessing Kong Manager at `https://admin.kong.example/` and +the Admin API at `https://admin.kong.example/_api/`. This option requires +placing a proxy in front of both Kong Manager and the Admin API to handle +path-based routing; you can use Kong's proxy for this purpose. Note that the +GUIs must be served at the root of their domains; you cannot place the APIs at +the root and the GUI under a path. + +### Troubleshooting + +CORS errors are shown in the browser developer console (for example, see documentation for +[Firefox][firefox-dev-console] and [Chrome][chrome-dev-console]) with +explanations of the specific issue. ACAO/Origin mismatches are most common, but +other error conditions can appear as well. + +For example, if you have mistyped your `admin_api_uri`, you will see something +like the following: + +``` +Access to XMLHttpRequest at 'https://admin.kong.example' from origin 'https://manager.kong.example' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://typo.kong.example' that is not equal to the supplied origin. +``` + +These errors are generally self-explanatory, but if the issue is not clear, +check the Network developer tool, find the requests for the path in the error, +and compare its `Origin` request header and `Access-Control-Allow-Origin` +response header (it may be missing entirely). + +## Cookies + +### Understanding cookies + +[Cookies][mdn-cookies] are small pieces of data saved by browsers for use in +future requests. Servers include a [Set-Cookie header][mdn-set-cookie] in their +response headers to set cookies, and browsers include a [Cookie +header][mdn-cookie] when making subsequent requests. + +Cookies are used for a variety of purposes and offer many settings to tailor +when a browser will include them to fit a particular use case. Of particular +interest are the following directives: + +- Cookie scope, defined by the cookie's `Domain` and `Path` directives. Absent + these, cookies are sent only to the hostname that created them: a cookie + created by `example.com` will not be sent with a request to + `www.example.com`. When `Domain` is specified, cookies are sent to that + hostname and its subdomains, so a cookie from `example.com` with + `Domain=example.com` *will* be sent with requests to `www.example.com`. +- The `Secure` directive, which determines whether a cookie can be sent over an + unencrypted (HTTP rather than HTTPS) connection. A cookie with `Secure` + cannot be sent over HTTP, and must be set using HTTPS. +- The `SameSite` directive, which controls when a cookie can be sent with + cross-origin requests. Note that cookies have a different notion of + cross-origin than CORS and check against the domain suffix: while + `example.com` sending a request to `api.example.com` is cross-origin for the + purposes of CORS, a cookie with `Domain=example.com` is considered same-site + for requests to `api.example.com`. `SameSite=Strict` cookies are only sent + with same-site requests, `Lax` are sent when navigating to a link from + another site, and `None` are sent with all cross-origin requests. + +### Cookies in the context of {{site.base_gateway}} + +After you log in to Kong Manager or the Dev Portal, Kong stores session +information in a cookie to recognize your browser during future requests. These +cookies are created using the [session plugin][session-plugin] (via +`admin_gui_session_conf`) or [OpenID Connect plugin][oidc-plugin]. +Configuration is more or less the same between each--the OpenID Connect plugin +contains an embedded version of the session plugin, so while cookie handling +code is the same, it is configured directly in the OpenID Connect plugin +settings (`admin_gui_auth_conf`). + +- `cookie_name` does not affect where the cookie is used, but should be set to + a unique value to avoid collisions: some configurations may use the same + `cookie_domain` for both admin and Portal cookies, and using the same name + for both would then cause their cookies to collide and overwrite one another. +- `cookie_domain` should match the common hostname suffix shared by the GUI and + its API. For example, if you use `api.admin.kong.example` and + `manager.admin.kong.example` for the Admin API and Kong Manager, + `cookie_domain` should be `admin.kong.example`. +- `cookie_samesite` should typically be left at its default, `strict`. `none` + is not necessary if you have your DNS records and `cookie_domain` set + following the examples in this document. `off` is only needed if the GUI and + API are on entirely separate hostnames, e.g. `admin.kong.example` for the API + and `manager.example.com` for Kong Manager. This configuration is not + recommended because `off` opens a vector for cross-site request forgery + attacks. It may be needed in some development or testing environments, but + should not be used in production. +- `cookie_secure` controls whether cookies can be sent over unsecured + (plaintext HTTP) requests. By default, it is set to `true`, which does not + permit sending the cookie over unsecured connections. This setting should + also remain on the default, but may be disabled in some development or + testing environments where HTTPS is not used. + +OpenID Connect uses the same settings, but prefixed with `session_`, e.g. +`session_cookie_name` rather than `cookie_name`. + +Dev Portal configuration does not differ significantly from Kong Manager +configuration, but is configured per workspace under the Portal > Settings +section of Kong Manager, in the "Session Config (JSON)" field. + +As with CORS, the above is not necessary if both the GUI and API use the same +hostname, with both behind a proxy and the API under a specific path on the +hostname. + +### Troubleshooting + +Issues with session cookies broadly fall into cases where the cookie is not +sent and cases where the cookie is not set. The network (for example, see documentation for +[Firefox][firefox-dev-network] or [Chrome][chrome-dev-network]) and +application/storage (see documentation for [Firefox][firefox-dev-storage] or +[Chrome][chrome-dev-application]) developer tools can assist with investigating +these. + +In the network tool, selecting individual requests will show their request and +response headers. Successful authentication requests should see a `Set-Cookie` +response header including a cookie whose name matches `cookie_name` setting, +and subsequent requests should include the same cookie in the `Cookie` request +header. + +If `Set-Cookie` is not present, it may be being stripped by some intermediate +proxy, or may indicate that the authentication handler encountered an error. +There should typically be other evidence in the response status and body in the +event of an error, and possible additional information in Kong's error logs. + +If the cookie is set but not sent, it may have been deleted or may not match +requests that need it. The application/storage tool will show current cookies +and their parameters. Review these to see if your requests do not meet the +criteria to send the cookie (e.g. the cookie domain is not a suffix for a +request that requires the cookie, or is not present) and adjust your session +configuration accordingly. + +If cookies are *not* present in application/storage, but were previously set +with `Set-Cookie`, they may have since been deleted, or may have expired. +Review the `Set-Cookie` information to see when the cookie was set to expire +and subsequent requests to determine if any other response has issued a +`Set-Cookie` that deleted it (by setting expiration to a date in the past). + +This troubleshooting information may not immediately indicate the cause of the issue, but can +help Kong Support pinpoint the cause. Please provide it in tickets if possible. + +[chrome-dev-application]: https://developers.google.com/web/tools/chrome-devtools#application +[chrome-dev-console]: https://developers.google.com/web/tools/chrome-devtools/console/log +[chrome-dev-network]: https://developers.google.com/web/tools/chrome-devtools#network +[firefox-dev-console]: https://developer.mozilla.org/en-US/docs/Tools/Web_Console/Opening_the_Web_Console +[firefox-dev-network]: https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor +[firefox-dev-storage]: https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector +[mdn-cookie]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cookie +[mdn-cookies]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies +[mdn-set-cookie]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie +[mdn-cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS +[oidc-plugin]: /hub/kong-inc/openid-connect/ +[session-plugin]: /hub/kong-inc/session/ diff --git a/app/gateway/2.7.x/plan-and-deploy/hybrid-mode/hybrid-mode-setup.md b/app/gateway/2.7.x/plan-and-deploy/hybrid-mode/hybrid-mode-setup.md new file mode 100644 index 000000000000..60f2f0e7f401 --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/hybrid-mode/hybrid-mode-setup.md @@ -0,0 +1,699 @@ +--- +title: Deploy Kong Gateway in Hybrid Mode +--- + +## Prerequisites + +To get started with a hybrid mode deployment, first install an instance of +{{site.base_gateway}} with TLS to be your control plane (CP) node. See the +[installation documentation](/gateway/{{page.release}}/install-and-run/) +for details. + +We will bring up any subsequent data plane (DP) instances in this topic. + +{:.note} +> **Note:** For a hybrid mode deployment on Kubernetes, see [hybrid mode](https://github.com/Kong/charts/blob/main/charts/kong/README.md#hybrid-mode) +in the `kong/charts` repository. + +## Generate a certificate/key pair + +In hybrid mode, a mutual TLS handshake (mTLS) is used for authentication so the +actual private key is never transferred on the network, and communication +between CP and DP nodes is secure. + +Before using hybrid mode, you need a certificate/key pair. +{{site.base_gateway}} provides two modes for handling certificate/key pairs: + +* **Shared mode:** (Default) Use the Kong CLI to generate a certificate/key +pair, then distribute copies across nodes. The certificate/key pair is shared +by both CP and DP nodes. +* **PKI mode:** Provide certificates signed by a central certificate authority +(CA). Kong validates both sides by checking if they are from the same CA. This +eliminates the risks associated with transporting private keys. + +{:.warning} +> **Warning:** If you have a TLS-aware proxy between the DP and CP nodes, you +must use PKI mode and set `cluster_server_name` to the CP hostname in +`kong.conf`. Do not use shared mode, as it uses a non-standard value for TLS server name +indication, and this will confuse TLS-aware proxies that rely on SNI to route +traffic. + +For a breakdown of the properties used by these modes, see the +[configuration reference](#configuration-reference). + +{% navtabs %} +{% navtab Shared mode %} +{:.warning} + > **Warning:** Protect the Private Key. Ensure the private key file can only be accessed by + Kong nodes belonging to the cluster. If the key is compromised, you must + regenerate and replace certificates and keys on all CP and DP nodes. + +1. On an existing {{site.base_gateway}} instance, create a certificate/key pair: + ```bash + kong hybrid gen_cert + ``` + This will generate `cluster.crt` and `cluster.key` files and save them to + the current directory. By default, the certificate/key pair is valid for three + years, but can be adjusted with the `--days` option. See `kong hybrid --help` + for more usage information. + +2. Copy the `cluster.crt` and `cluster.key` files to the same directory +on all Kong CP and DP nodes; e.g., `/cluster/cluster`. + Set appropriate permissions on the key file so it can only be read by Kong. + +{% endnavtab %} +{% navtab PKI mode %} + +With PKI mode, the Hybrid cluster can use certificates signed by a central +certificate authority (CA). + +In this mode, the control plane and data plane don't need to use the same +`cluster_cert` and `cluster_cert_key`. Instead, Kong validates both sides by +checking if they are from the same CA. + +Prepare your CA certificates on the hosts where Kong will be running. + +{% navtabs %} +{% navtab CA Certificate Example %} +Typically, a CA certificate will look like this: + +``` +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 5d:29:73:bf:c3:da:5f:60:69:da:73:ed:0e:2e:97:6f:7f:4c:db:4b + Signature Algorithm: ecdsa-with-SHA256 + Issuer: O = Kong Inc., CN = Hybrid Root CA + Validity + Not Before: Jul 7 12:36:10 2020 GMT + Not After : Jul 7 12:36:40 2023 GMT + Subject: O = Kong Inc., CN = Hybrid Root CA + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:df:49:9f:39:e6:2c:52:9f:46:7a:df:ae:7b:9b: + 87:1e:76:bb:2e:1d:9c:61:77:07:e5:8a:ba:34:53: + 3a:27:4c:1e:76:23:b4:a2:08:80:b4:1f:18:7a:0b: + 79:de:ea:8c:23:94:e6:2f:57:cf:27:b4:0a:52:59: + 90:2c:2b:86:03 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 8A:0F:07:61:1A:0F:F4:B4:5D:B7:F3:B7:28:D1:C5:4B:81:A2:B9:25 + X509v3 Authority Key Identifier: + keyid:8A:0F:07:61:1A:0F:F4:B4:5D:B7:F3:B7:28:D1:C5:4B:81:A2:B9:25 + + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:20:68:3c:d1:f3:63:a2:aa:b4:59:c9:52:af:33:b7: + 3f:ca:3a:2b:1c:9d:87:0c:c0:47:ff:a2:c4:af:3e:b0:36:29: + 02:21:00:86:ce:d0:fc:ba:92:e9:59:16:1c:c3:b2:11:11:ed: + 01:5d:16:49:d0:f9:0c:1d:35:0d:40:ba:19:98:31:76:57 +``` +{% endnavtab %} + +{% navtab CA Certificate on CP %} +Here is an example of a CA certificate on a control plane: + +``` +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 18:cc:a3:6b:aa:77:0a:69:c6:d5:ff:12:be:be:c0:ac:5c:ff:f1:1e + Signature Algorithm: ecdsa-with-SHA256 + Issuer: CN = Hybrid Intermediate CA + Validity + Not Before: Jul 31 00:59:29 2020 GMT + Not After : Oct 29 00:59:59 2020 GMT + Subject: CN = control-plane.kong.yourcorp.tld + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:f8:3a:a9:d2:e2:79:19:19:f3:1c:58:a0:23:60: + 78:04:1f:7e:e2:bb:60:d2:29:50:ad:7c:9b:8e:22: + 1c:54:c2:ce:68:b8:6c:8a:f6:92:9d:0c:ce:08:d3: + aa:0c:20:67:41:32:18:63:c9:dd:50:31:60:d6:8b: + 8d:f9:7b:b5:37 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Server Authentication + X509v3 Subject Key Identifier: + 70:C7:F0:3B:CD:EB:8D:1B:FF:6A:7C:E0:A4:F0:C6:4C:4A:19:B8:7F + X509v3 Authority Key Identifier: + keyid:16:0D:CF:92:3B:31:B0:61:E5:AB:EE:91:42:B9:60:56:0A:88:92:82 + + X509v3 Subject Alternative Name: + DNS:control-plane.kong.yourcorp.tld, DNS:alternate-control-plane.kong.yourcorp.tld + X509v3 CRL Distribution Points: + + Full Name: + URI:https://crl-service.yourcorp.tld/v1/pki/crl + + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:5d:dd:ec:a8:4f:e7:5b:7d:2f:3f:ec:b5:40:d7: + de:5e:96:e1:db:b7:73:d6:84:2e:be:89:93:77:f1:05:07:f3: + 02:20:16:56:d9:90:06:cf:98:07:87:33:dc:ef:f4:cc:6b:d1: + 19:8f:64:ee:82:a6:e8:e6:de:57:a7:24:82:72:82:49 +``` +{% endnavtab %} + +{% navtab CA Certificate on DP %} +Here is an example of a CA certificate on a data plane: + +``` +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 4d:8b:eb:89:a2:ed:b5:29:80:94:31:e4:94:86:ce:4f:98:5a:ad:a0 + Signature Algorithm: ecdsa-with-SHA256 + Issuer: CN = Hybrid Intermediate CA + Validity + Not Before: Jul 31 00:57:01 2020 GMT + Not After : Oct 29 00:57:31 2020 GMT + Subject: CN = kong-dp-ce39edecp.service + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:19:51:80:4c:6d:8c:a8:05:63:42:71:a2:9a:23: + 34:34:92:c6:2a:d3:e5:15:6e:36:44:85:64:0a:4c: + 12:16:82:3f:b7:4c:e1:a1:5a:49:5d:4c:5e:af:3c: + c1:37:e7:91:e2:b5:52:41:a0:51:ac:13:7b:cc:69: + 93:82:9b:2f:e2 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Key Agreement + X509v3 Extended Key Usage: + TLS Web Client Authentication + X509v3 Subject Key Identifier: + 25:82:8C:93:85:35:C3:D6:34:CF:CB:7B:D6:14:97:46:84:B9:2B:87 + X509v3 Authority Key Identifier: + keyid:16:0D:CF:92:3B:31:B0:61:E5:AB:EE:91:42:B9:60:56:0A:88:92:82 + X509v3 CRL Distribution Points: + + Full Name: + URI:https://crl-service.yourcorp.tld/v1/pki/crl + + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:65:2f:5e:30:f7:a4:28:14:88:53:58:c5:85:24: + 35:50:25:c9:fe:db:2f:72:9f:ad:7d:a0:67:67:36:32:2b:d2: + 02:20:2a:27:7d:eb:75:a6:ee:65:8b:f1:66:a4:99:32:56:7c: + ad:ca:3a:d5:50:8f:cf:aa:6d:c2:1c:af:a4:ca:75:e8 +``` +{% endnavtab %} +{% endnavtabs %} + +> **Note:** Certificates on CP and DP must contain the `TLS Web Server Authentication` and +`TLS Web Client Authentication` as X509v3 Extended Key Usage extension, respectively. + +Kong doesn't validate the CommonName (CN) in the DP certificate; it can take an arbitrary value. + +{% endnavtab %} +{% endnavtabs %} + +## Set up the control plane +Next, give the control plane node the `control_plane` role, and set +certificate/key parameters to point at the location of your certificates and +keys. + +{% navtabs %} +{% navtab Using Docker %} + +1. In your Docker container, set the following environment variables: + + For `shared` certificate mode, use: + ```bash + KONG_ROLE=control_plane + KONG_CLUSTER_CERT=//cluster.crt + KONG_CLUSTER_CERT_KEY=//cluster.key + ``` + + For `pki` certificate mode, use: + ```bash + KONG_ROLE=control_plane + KONG_CLUSTER_MTLS=pki + KONG_CLUSTER_CA_CERT=//ca-cert.pem + KONG_CLUSTER_CERT=//control-plane.crt + KONG_CLUSTER_CERT_KEY=//control-plane.key + ``` + By setting the role of the node to `control_plane`, this node will listen on + port `0.0.0.0:8005` by default for data plane connections, and on port + `0.0.0.0:8006` for telemetry data. These ports on the + control plane will need to be accessible by all data planes it controls through + any firewalls you may have in place. + + For PKI mode, `KONG_CLUSTER_CA_CERT` specifies the root CA certificate for + `KONG_CLUSTER_CERT` and `KONG_CLUSTER_CERT_KEY`. This certificate must be + the root CA certificate and not any of an intermediate CA. Kong allows a + maximum of three levels of intermediate CAs to be used between the root CA + and the cluster certificate. + + If you need to change the ports that the control plane listens on, set: + ```bash + KONG_CLUSTER_LISTEN=0.0.0.0: + KONG_CLUSTER_TELEMETRY_LISTEN=0.0.0.0: + ``` + +2. Next, start Kong, or reload Kong if it's already running: + ```bash + kong start + ``` + ```bash + kong reload + ``` + +{% endnavtab %} +{% navtab Using kong.conf %} +1. In `kong.conf`, set the following configuration parameters: + + For `shared` certificate mode, use: + ```bash + role = control_plane + cluster_cert = //cluster.crt + cluster_cert_key = //cluster.key + ``` + + For `pki` certificate mode, use: + ```bash + role = control_plane + cluster_mtls = pki + cluster_ca_cert = //ca-cert.pem + cluster_cert = //control-plane.crt + cluster_cert_key = //control-plane.key + ``` + + By setting the role of the node to `control_plane`, this node will listen on + port `0.0.0.0:8005` by default for data plane connections, and on port + `0.0.0.0:8006` for telemetry data. These ports on the + control plane will need to be accessible by all data planes it controls through + any firewalls you may have in place. + + For PKI mode, `cluster_ca_cert` specifies the root CA certificate for + `cluster_cert` and `cluster_cert_key`. This certificate must be the root CA + certificate and not any of an intermediate CA. Kong allows a maximum of three + levels of intermediate CAs to be used between the root CA and the cluster + certificate. + + If you need to change the ports that the control plane listens on, set: + ```bash + cluster_listen=0.0.0.0: + cluster_telemetry_listen=0.0.0.0: + ``` + +2. Restart Kong for the settings to take effect: + ```bash + kong restart + ``` +{% endnavtab %} +{% endnavtabs %} + +Note that the control plane still needs a database to +store the central configurations, although the database never needs to +be accessed by data plane nodes. You may run multiple control plane nodes to +provide load balancing and redundancy, as long as they all point to the same +backend database. + +{:.note} +> **Note:** Control plane nodes cannot be used for proxying. + +### (Optional) Revocation checks of data plane certificates + +When Kong is running hybrid mode with PKI mode, the control plane can be configured to +optionally check for revocation status of the connecting data plane certificate. + +The supported method is through Online Certificate Status Protocol (OCSP) responders. +Issued data plane certificates must contain the Certificate Authority Information Access extension +that references the URI of OCSP responder that can be reached from the control plane. + +To enable OCSP checks, set the `cluster_ocsp` config on the control plane to one of the following values: + +* `on`: OCSP revocation check is enabled and the data plane must pass the revocation check +to establish connection with the control plane. This implies that certificates without the +OCSP extension or unreachable OCSP responder also prevents a connection from being established. +* `off`: OCSP revocation check is disabled (default). +* `optional`: OCSP revocation check will be attempted, however, if the OCSP responder URI is not +found inside the data plane-provided certificate or communication with the OCSP responder failed, +then data plane is still allowed through. + +Note that OCSP checks are only performed on the control plane against certificates provided by incoming data plane +nodes. The `cluster_ocsp` config has no effect on data plane nodes. +`cluster_oscp` affects all hybrid mode connections established from a data plane to its control plane. + +## Install and start data planes +Now that the control plane is running, you can attach data plane nodes to it to +start serving traffic. + +In this step, you will give all data plane nodes the `data_plane` role, +point them to the control plane, set certificate/key parameters to point at +the location of your certificates and keys, and ensure the database +is disabled. + +In addition, the certificate from `cluster_cert` (in `shared` mode) or `cluster_ca_cert` +(in `pki` mode) is automatically added to the trusted chain in +[`lua_ssl_trusted_certificate`](/gateway/{{page.release}}/reference/configuration/#lua_ssl_trusted_certificate). + +{:.important} +> **Important:** Data plane nodes receive updates from the control plane via a format +similar to declarative config, therefore `database` has to be set to +`off` for Kong to start up properly. + +See the [DP node start sequence](#dp-node-start-sequence) for more information +on how data plane nodes process configuration. + + +{% navtabs %} +{% navtab Using Docker %} +1. Using the [Docker installation documentation](/gateway/{{page.release}}/install-and-run/docker/), +follow the instructions to: + 1. [Download {{site.base_gateway}}](/gateway/{{page.release}}/install-and-run/docker/). + 2. [Create a Docker network](/gateway/{{page.release}}/install-and-run/docker/#install-gateway-in-db-less-mode). + + {:.warning} + > **Warning:** Do not start or create a database on this node. + + +1. Bring up your data plane container with the following settings: + + For `shared` certificate mode, use: + +{% capture shared-mode-cp %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```bash +docker run -d --name kong-dp --network=kong-net \ +-e "KONG_ROLE=data_plane" \ +-e "KONG_DATABASE=off" \ +-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \ +-e "KONG_CLUSTER_CONTROL_PLANE=control-plane..com:8005" \ +-e "KONG_CLUSTER_TELEMETRY_ENDPOINT=control-plane..com:8006" \ +-e "KONG_CLUSTER_CERT=//cluster.crt" \ +-e "KONG_CLUSTER_CERT_KEY=//cluster.key" \ +--mount type=bind,source="$(pwd)"/cluster,target=,readonly \ +-p 8000:8000 \ +kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +docker run -d --name kong-dp --network=kong-net \ +-e "KONG_ROLE=data_plane" \ +-e "KONG_DATABASE=off" \ +-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \ +-e "KONG_CLUSTER_CONTROL_PLANE=control-plane..com:8005" \ +-e "KONG_CLUSTER_TELEMETRY_ENDPOINT=control-plane..com:8006" \ +-e "KONG_CLUSTER_CERT=//cluster.crt" \ +-e "KONG_CLUSTER_CERT_KEY=//cluster.key" \ +--mount type=bind,source="$(pwd)"/cluster,target=,readonly \ +-p 8000:8000 \ +kong:{{page.releases_hash[page.version-index].ce-version}}-alpine +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ shared-mode-cp | indent | replace: " ", "" }} + + For `pki` certificate mode, use: + +{% capture pki-mode-cp %} +{% navtabs codeblock %} +{% navtab Kong Gateway %} +```bash +docker run -d --name kong-dp --network=kong-net \ +-e "KONG_ROLE=data_plane" \ +-e "KONG_DATABASE=off" \ +-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \ +-e "KONG_CLUSTER_CONTROL_PLANE=control-plane..com:8005" \ +-e "KONG_CLUSTER_TELEMETRY_ENDPOINT=control-plane..com:8006" \ +-e "KONG_CLUSTER_MTLS=pki" \ +-e "KONG_CLUSTER_SERVER_NAME=control-plane.kong.yourcorp.tld" \ +-e "KONG_CLUSTER_CERT=data-plane.crt" \ +-e "KONG_CLUSTER_CERT_KEY=//data-plane.crt" \ +-e "KONG_CLUSTER_CA_CERT=//ca-cert.pem" \ +--mount type=bind,source="$(pwd)"/cluster,target=,readonly \ +-p 8000:8000 \ +kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine +``` +{% endnavtab %} +{% navtab Kong Gateway (OSS) %} +```bash +docker run -d --name kong-dp --network=kong-net \ +-e "KONG_ROLE=data_plane" \ +-e "KONG_DATABASE=off" \ +-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \ +-e "KONG_CLUSTER_CONTROL_PLANE=control-plane..com:8005" \ +-e "KONG_CLUSTER_TELEMETRY_ENDPOINT=control-plane..com:8006" \ +-e "KONG_CLUSTER_MTLS=pki" \ +-e "KONG_CLUSTER_SERVER_NAME=control-plane.kong.yourcorp.tld" \ +-e "KONG_CLUSTER_CERT=data-plane.crt" \ +-e "KONG_CLUSTER_CERT_KEY=//data-plane.crt" \ +-e "KONG_CLUSTER_CA_CERT=//ca-cert.pem" \ +--mount type=bind,source="$(pwd)"/cluster,target=,readonly \ +-p 8000:8000 \ +kong:{{page.releases_hash[page.version-index].ce-version}}-alpine +``` +{% endnavtab %} +{% endnavtabs %} +{% endcapture %} +{{ pki-mode-cp | indent | replace: " ", "" }} + + Where: + + `--name` and `--network` + : The tag of the {{site.base_gateway}} image that you're using, and the Docker network it communicates on. + + `KONG_CLUSTER_CONTROL_PLANE` + : Sets the address and port of the control plane (port `8005` by default). + + `KONG_DATABASE` + : Specifies whether this node connects directly to a database. + + `` and `target=` + : Are the same path, pointing to the location of the `cluster.key` and + `cluster.crt` files. + + `KONG_CLUSTER_SERVER_NAME` + : Specifies the SNI (Server Name Indication + extension) to use for data plane connections to the control plane through + TLS. When not set, data plane will use `kong_clustering` as the SNI. + + : You can also optionally use `KONG_CLUSTER_TELEMETRY_SERVER_NAME` + to set a custom SNI for telemetry data. If not set, it defaults to + `KONG_CLUSTER_SERVER_NAME`. + + `KONG_CLUSTER_TELEMETRY_ENDPOINT` + : Optional setting, needed for telemetry gathering. Not available in open-source deployments. + + You can also choose to encrypt or disable the data plane configuration + cache with some additional settings: + + `KONG_DATA_PLANE_CONFIG_CACHE_MODE` + : Optional setting for storing the config cache, defaults to `unencrypted`. + Change this to `encrypted` if you want to store the data plane's config cache + in an encrypted format, or set it to `off` if you don't want to use a cache. + Not available in open-source deployments. + + `KONG_DATA_PLANE_CONFIG_CACHE_PATH` + : An optional custom path to the config cache. Not available in open-source + deployments. + +1. If needed, bring up any subsequent data planes using the same settings. + +{% endnavtab %} +{% navtab Using kong.conf %} + +1. Find the documentation for [your platform](/gateway/{{page.release}}/install-and-run/), +and follow the instructions in Steps 1 and 2 **only** to download +{{site.base_gateway}} and install Kong. + + {:.note} + > **Note:** for Docker, see the **Docker** tab above. For Kubernetes, see the + [hybrid mode documentation](https://github.com/Kong/charts/blob/main/charts/kong/README.md#hybrid-mode) + in the `kong/charts` repository. + + {:.warning} + > Do not start or create a database on this node. + + +2. In `kong.conf`, set the following configuration parameters: + + For `shared` certificate mode, use: + ```bash + role = data_plane + database = off + proxy_listen = 0.0.0.0:8000 + cluster_control_plane = control-plane..com:8005 + cluster_telemetry_endpoint = control-plane..com:8006 + cluster_cert = //cluster.crt + cluster_cert_key = //cluster.key + ``` + + For `pki` certificate mode, use: + ```bash + role = data_plane + database = off + proxy_listen = 0.0.0.0:8000 + cluster_control_plane = control-plane..com:8005 + cluster_telemetry_endpoint = control-plane..com:8006 + cluster_mtls = pki + cluster_server_name = control-plane.kong.yourcorp.tld + cluster_cert = //data-plane.crt + cluster_cert_key = //data-plane.crt + cluster_ca_cert = //ca-cert.pem + ``` + + Where: + + `cluster_control_plane` + : Sets the address and port of the control plane (port `8005` by default). + + `database` + : Specifies whether this node connects directly to a database. + + `` + : Specifies the location of the `cluster.key` and `cluster.crt` files. + + `cluster_server_name` + : Specifies the SNI (Server Name Indication extension) + to use for data plane connections to the control plane through TLS. When + not set, data plane will use `kong_clustering` as the SNI. + + : You can also optionally use `cluster_telemetry_server_name` + to set a custom SNI for telemetry data. If not set, it defaults to + `cluster_server_name`. + + `cluster_telemetry_endpoint` + : Optional setting, needed for telemetry gathering. Not available in open-source deployments. + + You can also choose to encrypt or disable the data plane configuration + cache with some additional settings: + + `data_plane_config_cache_mode` + : Optional setting for storing the config cache, defaults to `unencrypted`. + Change this to `encrypted` if you want to store the data plane's config cache + in an encrypted format, or set it to `off` if you don't want to use a cache. + Not available in open-source deployments. + + `data_plane_config_cache_path` + : An optional custom path to the config cache. Not available in open-source + deployments. + +3. Restart Kong for the settings to take effect: + ```bash + kong restart + ``` +{% endnavtab %} +{% endnavtabs %} + +## Verify that nodes are connected + +Use the control plane’s Cluster Status API to monitor your data planes. It +provides: +* The name of the node +* The last time the node synced with the control plane +* The version of the config currently running on each data plane + +To check whether the CP and DP nodes you just brought up are connected, run the +following on a control plane: +{% navtabs %} +{% navtab Using cURL %} +```bash +curl -i -X GET http://localhost:8001/clustering/data-planes +``` +{% endnavtab %} +{% navtab Using HTTPie %} +```bash +http :8001/clustering/data-planes +``` +{% endnavtab %} +{% endnavtabs %} +The output shows all of the connected data plane instances in the cluster: + +```json +{ + "data": [ + { + "config_hash": "a9a166c59873245db8f1a747ba9a80a7", + "hostname": "data-plane-2", + "id": "ed58ac85-dba6-4946-999d-e8b5071607d4", + "ip": "192.168.10.3", + "last_seen": 1580623199, + "status": "connected" + }, + { + "config_hash": "a9a166c59873245db8f1a747ba9a80a7", + "hostname": "data-plane-1", + "id": "ed58ac85-dba6-4946-999d-e8b5071607d4", + "ip": "192.168.10.4", + "last_seen": 1580623200, + "status": "connected" + } + ], + "next": null +} +``` + +## References + +### DP node start sequence + +When set as a DP node, {{site.base_gateway}} processes configuration in the +following order: + +1. **Config cache**: If the file `config.json.gz` exists in the `kong_prefix` +path (`/usr/local/kong` by default), the DP node loads it as configuration. +2. **`declarative_config` exists**: If there is no config cache and the +`declarative_config` parameter is set, the DP node loads the specified file. +3. **Empty config**: If there is no config cache or declarative +configuration file available, the node starts with empty configuration. In this +state, it returns 404 to all requests. +4. **Contact CP Node**: In all cases, the DP node contacts the CP node to retrieve +the latest configuration. If successful, it gets stored in the local config +cache (`config.json.gz`). + +### Configuration reference + +Use the following configuration properties to configure {{site.base_gateway}} +in hybrid mode. + +Parameter | Description | CP or DP {:width=10%:} +--------- | ----------- | ---------------------- +[`role`](/gateway/{{page.release}}/reference/configuration/#role)
    *Required* | Determines whether the {{site.base_gateway}} instance is a control plane or a data plane. Valid values are `control_plane` or `data_plane`. | Both +[`cluster_listen`](/gateway/{{page.release}}/reference/configuration/#cluster_listen)
    *Optional*

    **Default:** `0.0.0.0:8005`| List of addresses and ports on which the control plane will listen for incoming data plane connections. This port is always protected with Mutual TLS (mTLS) encryption. Ignored on data plane nodes. | CP +[`proxy_listen`](/gateway/{{page.release}}/reference/configuration/#proxy_listen)
    *Required* | Comma-separated list of addresses and ports on which the proxy server should listen for HTTP/HTTPS traffic. Ignored on control plane nodes. | DP +[`cluster_telemetry_listen`](/gateway/{{page.release}}/reference/configuration/#cluster_telemetry_listen)
    *Optional*

    **Default:** `0.0.0.0:8006`| List of addresses and ports on which the control plane will listen for data plane telemetry data. This port is always protected with Mutual TLS (mTLS) encryption. Ignored on data plane nodes. | CP +[`cluster_telemetry_endpoint`](/gateway/{{page.release}}/reference/configuration/#cluster_telemetry_endpoint)
    *Required for Enterprise deployments* | The port that the data plane uses to send telemetry data to the control plane. Ignored on control plane nodes. | DP +[`cluster_control_plane`](/gateway/{{page.release}}/reference/configuration/#cluster_control_plane)
    *Required* | Address and port that the data plane nodes use to connect to the control plane. Must point to the port configured using the [`cluster_listen`](/gateway/{{page.release}}/reference/configuration/#cluster_listen) property on the control plane node. Ignored on control plane nodes. | DP +[`cluster_mtls`](/gateway/{{page.release}}/reference/configuration/#cluster_mtls)
    *Optional*

    **Default:** `shared` | One of `shared` or `pki`. Indicates whether hybrid mode will use a shared certificate/key pair for CP/DP mTLS or if PKI mode will be used. See below sections for differences in mTLS modes. | Both +[`data_plane_config_cache_mode`](/gateway/{{page.release}}/reference/configuration/#data_plane_config_cache_mode)
    *Optional*

    **Default:** `unencrypted` | Determines how the data plane configuration cache is stored.
    • `unencrypted`: Stores configuration without encrypting it in `config.cache.json.gz`
    • `encrypted`: Encrypts and stores the configuration cache in `.config.cache.jwt` (hidden file).
    • `off`: The data plane does not cache configuration | DP +[`data_plane_config_cache_path`](/gateway/{{page.release}}/reference/configuration/#data_plane_config_cache_path)
    *Optional*

    **Default:** Kong [`prefix` path](/gateway/{{page.release}}/reference/configuration/#prefix) | Path to the data plane config cache file, for example `/tmp/kong-config-cache`. If the cache mode is `encrypted`, the filename is `.config.cache.jwt` (hidden file). If the cache mode is `unencrypted`, the filename is `config.cache.json.gz`. | DP + +The following properties are used differently between `shared` and `pki` modes: + +Parameter | Description | Shared Mode {:width=12%:} | PKI Mode {:width=30%:} +--------- | ----------- | ------------------------- | ---------------------- +[`cluster_cert`](/gateway/{{page.release}}/reference/configuration/#cluster_cert) and [`cluster_cert_key`](/gateway/{{page.release}}/reference/configuration/#cluster_cert_key)
    *Required* | Certificate/key pair used for mTLS between CP/DP nodes. | Same between CP/DP nodes. | Unique certificate for each node, generated from the CA specified by `cluster_ca_cert`. +[`cluster_ca_cert`](/gateway/{{page.release}}/reference/configuration/#cluster_ca_cert)
    *Required in PKI mode* | The trusted CA certificate file in PEM format used to verify the `cluster_cert`. | *Ignored* | CA certificate used to verify `cluster_cert`, same between CP/DP nodes. *Required* +[`cluster_server_name`](/gateway/{{page.release}}/reference/configuration/#cluster_server_name)
    *Required in PKI mode* | The SNI presented by the DP node mTLS handshake. | *Ignored* | In PKI mode, the DP nodes will also verify that the Common Name (CN) or Subject Alternative Name (SAN) inside the certificate presented by CP matches the `cluster_server_name` value. +[`cluster_telemetry_server_name`](/gateway/{{page.release}}/reference/configuration/#cluster_telemetry_server_name) | The telemetry SNI presented by the DP node mTLS handshake. If not specified, falls back on SNI set in `cluster_server_name`. | *Ignored* | In PKI mode, the DP nodes will also verify that the Common Name (CN) or Subject Alternative Name (SAN) inside the certificate presented by CP matches the `cluster_telemetry_server_name` value. + +## Next steps + +Now, you can start managing the cluster using the control plane. Once +all instances are set up, use the Admin API on the control plane as usual, and +these changes will be synced and updated on the data plane nodes automatically +within seconds. diff --git a/app/gateway/2.7.x/plan-and-deploy/hybrid-mode/index.md b/app/gateway/2.7.x/plan-and-deploy/hybrid-mode/index.md new file mode 100644 index 000000000000..0cd61703bff5 --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/hybrid-mode/index.md @@ -0,0 +1,247 @@ +--- +title: Hybrid Mode Overview +--- + +Traditionally, Kong has always required a database, to store configured +entities such as Routes, Services, and Plugins. + +Starting with {{site.base_gateway}} 2.1, Kong can be deployed in +hybrid mode, also known as control plane / data plane separation (CP/DP). + +In this mode, Kong nodes in a cluster are split into two roles: control plane +(CP), where configuration is managed and the Admin API is served from; and data +plane (DP), which serves traffic for the proxy. Each DP node is connected to one +of the CP nodes. Instead of accessing the database contents directly in the +traditional deployment method, the DP nodes maintain connection with CP nodes, +and receive the latest configuration. + +![Hybrid mode topology](/assets/images/products/gateway/deployment-hybrid-2.png) + +When you create a new data plane node, it establishes a connection to the +control plane. The control plane listens on port 8005 for connections and +tracks any incoming data from its data planes. + +Once connected, every Admin API or Kong Manager action on the control plane +triggers an update to the data planes in the cluster. + +## Benefits + +Hybrid mode deployments have the following benefits: + +* **Deployment flexibility:** Users can deploy groups of data planes in +different data centers, geographies, or zones without needing a local clustered +database for each DP group. +* **Increased reliability:** The availability of the database does not affect +the availability of the data planes. Each DP caches the latest configuration it +received from the control plane on local disk storage, so if CP nodes are down, +the DP nodes keep functioning. + * While the CP is down, DP nodes constantly try to reestablish communication. + * DP nodes can be restarted while the CP is down, and still proxy traffic + normally. +* **Traffic reduction:** Drastically reduces the amount of traffic to and from +the database, since only CP nodes need a direct connection to the database. +* **Increased security:** If one of the DP nodes is compromised, an attacker +won’t be able to affect other nodes in the Kong cluster. +* **Ease of management:** Admins only need to interact with the CP nodes to +control and monitor the status of the entire Kong cluster. + +## Platform Compatibility + +You can run {{site.base_gateway}} in hybrid mode on any platform where +{{site.base_gateway}} is [supported](/gateway/{{page.release}}/install-and-run/). + +### Kubernetes Support and Additional Documentation + +[{{site.base_gateway}} on Kubernetes](/gateway/{{page.release}}/install-and-run/kubernetes) +fully supports hybrid mode deployments, with or without the {{site.kic_product_name}}. + +For the full Kubernetes hybrid mode documentation, see +[hybrid mode](https://github.com/Kong/charts/blob/main/charts/kong/README.md#hybrid-mode) +in the `kong/charts` repository. + +## Version Compatibility + +{{site.base_gateway}} control planes only allow connections from data planes with the +same major version. +Control planes won't allow connections from data planes with newer minor versions. + +For example, a {{site.base_gateway}} v2.5.2 control plane: + +- Accepts a {{site.base_gateway}} 2.5.0, 2.5.1 and 2.5.2 data plane. +- Accepts a {{site.base_gateway}} 2.3.8, 2.2.1 and 2.2.0 data plane. +- Accepts a {{site.base_gateway}} 2.5.3 data plane (newer patch version on the data plane is accepted). +- Rejects a {{site.base_gateway}} 1.0.0 data plane (major version differs). +- Rejects a {{site.base_gateway}} 2.6.0 data plane (minor version on data plane is newer). + +Furthermore, for every plugin that is configured on the {{site.base_gateway}} +control plane, new configs are only pushed to data planes that have those configured +plugins installed and loaded. The major version of those configured plugins must +be the same on both the control planes and data planes. Also, the minor versions +of the plugins on the data planes can not be newer than versions installed on the +control planes. Similar to {{site.base_gateway}} version checks, +plugin patch versions are also ignored when determining compatibility. + +{:.important} +> Configured plugins means any plugin that is either enabled globally or +configured by services, routes, or consumers. + +For example, if a {{site.base_gateway}} control plane has `plugin1` v1.1.1 +and `plugin2` v2.1.0 installed, and `plugin1` is configured by a `Route` object: + +- It accepts {{site.base_gateway}} data planes with `plugin1` v1.1.2, +`plugin2` not installed. +- It accepts {{site.base_gateway}} data planes with `plugin1` v1.1.2, +`plugin2` v2.1.0, and `plugin3` v9.8.1 installed. +- It accepts {{site.base_gateway}} data planes with `plugin1` v1.1.1 +and `plugin3` v9.8.1 installed. +- It rejects {{site.base_gateway}} data planes with `plugin1` v1.2.0, +`plugin2` v2.1.0 installed (minor version of plugin on data plane is newer). +- It rejects {{site.base_gateway}} data planes with `plugin1` not installed +(plugin configured on control plane but not installed on data plane). + +Version compatibility checks between the control plane and data plane +occur at configuration read time. As each data plane proxy receives +configuration updates, it checks to see if it can enable the requested +features. If the control plane has a newer version of {{site.base_gateway}} +than the data plane proxy, but the configuration doesn’t include any new features +from that newer version, the data plane proxy reads and applies it as expected. + +For instance, a new version of {{site.base_gateway}} includes a new +plugin offering, and you update your control plane with that version. You can +still send configurations to your data planes that are on a less recent version +as long as you have not added the new plugin offering to your configuration. +If you add the new plugin to your configuration, you will need to update your +data planes to the newer version for the data planes to continue to read from +the control plane. + +If the compatibility checks fail, the control plane stops +pushing out new config to the incompatible data planes to avoid breaking them. + +If a config can not be pushed to a data plane due to failure of the +compatibility checks, the control plane will contain `warn` level lines in the +`error.log` similar to the following: + +```bash +unable to send updated configuration to DP node with hostname: localhost.localdomain ip: 127.0.0.1 reason: version mismatches, CP version: 2.2 DP version: 2.1 +unable to send updated configuration to DP node with hostname: localhost.localdomain ip: 127.0.0.1 reason: CP and DP does not have same set of plugins installed or their versions might differ +``` + +In addition, the `/clustering/data-planes` Admin API endpoint returns +the version of the data plane node and the latest config hash the node is +using. This data helps detect version incompatibilities from the +control plane side. + +## Fault tolerance + +If control plane nodes are down, the data plane will keep functioning. Data plane caches +the latest configuration it received from the control plane on the local disk. +In case the control plane stops working, the data plane will keep serving requests using +cached configurations. It does so while constantly trying to reestablish communication +with the control plane. + +This means that the data plane nodes can be stopped even for extended periods +of time, and the data plane will still proxy traffic normally. Data plane +nodes can be restarted while in disconnected mode, and will load the last +configuration in the cache to start working. When the control plane is brought +up again, the data plane nodes will contact them and resume connected mode. + +### Disconnected Mode + +The viability of the data plane while disconnected means that control plane +updates or database restores can be done with peace of mind. First bring down +the control plane, perform all required downtime processes, and only bring up +the control plane after verifying the success and correctness of the procedure. +During that time, the data plane will keep working with the latest configuration. + +A new data plane node can be provisioned during control plane downtime. This +requires either copying the config cache file (`config.json.gz`) from another +data plane node, or using a declarative configuration. In either case, if it +has the role of `"data_plane"`, it will also keep trying to contact the control +plane until it's up again. + +To change a disconnected data plane node's configuration, you have to remove +the config cache file (`config.json.gz`), ensure the `declarative_config` +parameter or the `KONG_DECLARATIVE_CONFIG` environment variable is set, and set +the whole configuration in the referenced YAML file. + +### Data plane cache configuration +{:.badge .enterprise} + +By default, data planes store their configuration to the file system +in an unencrypted cache file, `config.json.gz`, in {{site.base_gateway}}'s +`prefix` path. You can also choose to encrypt this cache, or disable it entirely. + +If encrypted, the data plane uses the cluster certificate key to decrypt the +configuration cache on startup. + +See [`data_plane_config_cache_mode`](/gateway/{{page.release}}/reference/configuration/#data_plane_config_cache_mode) +and [`data_plane_config_cache_path`](/gateway/{{page.release}}/reference/configuration/#data_plane_config_cache_path). + +### License deployment + +If you have an Enterprise license, the license file must be +deployed to control plane nodes. The control planes then distribute the license +to the data planes in their clusters. + +Use the [`/licenses`](/gateway/{{page.release}}/admin-api/licenses/reference/) +endpoint to apply the license to the control plane. + +## Limitations + +### Configuration Inflexibility + +When a configuration change is made at the control plane level via the Admin +API, it immediately triggers a cluster-wide update of all data plane +configurations. This means that the same configuration is synced from the CP to +all DPs, and the update cannot be scheduled or batched. For different DPs to +have different configurations, they will need their own CP instances. + +### Plugin Incompatibility + +When plugins are running on a data plane in hybrid mode, there is no Admin API +exposed directly from that DP. Since the Admin API is only exposed from the +control plane, all plugin configuration has to occur from the CP. Due to this +setup, and the configuration sync format between the CP and the DP, some plugins +have limitations in hybrid mode: + +* [**Key Auth Encrypted:**](/hub/kong-inc/key-auth-enc/) The time-to-live setting +(`ttl`), which determines the length of time a credential remains valid, does +not work in hybrid mode. +* [**Rate Limiting Advanced:**](/hub/kong-inc/rate-limiting-advanced/) +This plugin does not support the `cluster` strategy in hybrid mode. The `redis` +strategy must be used instead. +* [**OAuth 2.0 Authentication:**](/hub/kong-inc/oauth2/) This plugin is not +compatible with hybrid mode. For its regular workflow, the plugin needs to both +generate and delete tokens, and commit those changes to the database, which is +not possible with CP/DP separation. + +### Custom Plugins + +Custom plugins (either your own plugins or third-party plugins that are not +shipped with Kong) need to be installed on both the control plane and the data +plane in hybrid mode. + +### Load Balancing + +Currently, there is no automated load balancing for connections between the +control plane and the data plane. You can load balance manually by using +multiple control planes and redirecting the traffic using a TCP proxy. + +## Readonly Status API endpoints on data plane + +Several readonly endpoints from the [Admin API](/gateway/{{page.release}}/admin-api/) +are exposed to the [Status API](/gateway/{{page.release}}/reference/configuration/#status_listen) on data planes, including the following: + +- [GET /upstreams/{upstream}/targets/](/gateway/{{page.release}}/admin-api/#list-targets) +- [GET /upstreams/{upstream}/health/](/gateway/{{page.release}}/admin-api/#show-upstream-health-for-node) +- [GET /upstreams/{upstream}/targets/all/](/gateway/{{page.release}}/admin-api/#list-all-targets) +- GET /upstreams/{upstream}/targets/{target} + +Please refer to [Upstream objects](/gateway/{{page.release}}/admin-api/#upstream-object) in the Admin API documentation for more information about the +endpoints. + +## Keyring encryption in hybrid mode + +Because the keyring module encrypts data in the database, it can't encrypt +data on data plane nodes, since these nodes run without a database and get +data from the control plane. diff --git a/app/gateway/2.7.x/plan-and-deploy/kong-user.md b/app/gateway/2.7.x/plan-and-deploy/kong-user.md new file mode 100644 index 000000000000..95fbf007bbab --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/kong-user.md @@ -0,0 +1,60 @@ +--- +title: Running Kong as a Non-Root User +--- + +After installing {{site.base_gateway}} on a GNU/Linux system, you can +configure Kong to run as the built-in `kong` user and group instead of `root`. +This makes the Nginx master and worker processes run as the built-in `kong` +user and group, overriding any settings in the +[`nginx_user`](/gateway/{{page.release}}/reference/configuration/#nginx_user) +configuration property. It is also possible to run Kong as a custom non-root user. + +{:.important} +> **Important:** The Nginx master process needs to run as `root` for +Nginx to execute certain actions (for example, to listen on the privileged +port 80). +

    +> Although running Kong as the `kong` user and group +does provide more security, we advise that a system and network +administration evaluation be performed before making this decision. Otherwise, +Kong nodes might become unavailable due to insufficient permissions to execute +privileged system calls in the operating system. + +## Prerequisites + +{{site.ee_product_name}} is installed on one of the following Linux distributions: +* [Amazon Linux 1 or 2](/gateway/{{page.release}}/install-and-run/amazon-linux/) +* [CentOS](/gateway/{{page.release}}/install-and-run/centos/) +* [RHEL](/gateway/{{page.release}}/install-and-run/rhel/) +* [Ubuntu](/gateway/{{page.release}}/install-and-run/ubuntu/) + +## Run {{site.base_gateway}} as the built-in kong user + +When {{site.base_gateway}} is installed with a package management system such as `APT` or `YUM`, a default `kong` user and a default `kong` group are created. All the files installed by the package are owned by the `kong` user and group. + +1. Switch to the built-in `kong` user: + + ```sh + $ su kong + ``` +2. Start Kong: + + ```sh + kong start + ``` + +## Run {{site.base_gateway}} as a custom non-root user + +It is also possible to run Kong as a custom non-root user. Since all the files installed by the {{site.base_gateway}} package are owned by the `kong` group, a user that belongs to that group should be permitted to perform the same operations as the `kong` user. + +1. Add the user to the `kong` group + + ```sh + sudo usermod -aG kong your-user + ``` + +2. Start Kong: + + ```sh + kong start + ``` diff --git a/app/gateway/2.7.x/plan-and-deploy/kubernetes-deployment-options.md b/app/gateway/2.7.x/plan-and-deploy/kubernetes-deployment-options.md new file mode 100644 index 000000000000..0250f099afe0 --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/kubernetes-deployment-options.md @@ -0,0 +1,160 @@ +--- +title: Kubernetes Deployment Options +badge: enterprise +--- + +The {{site.kic_product_name}} translates Kubernetes resources into +{{site.base_gateway}} configuration. {{site.base_gateway}} uses that +configuration to route and control traffic. + +The [kong-gateway][enterprise-download] proxy image supports DB-less +operation and is recommended for all deployments. +* [DB-less installation with the {{site.kic_product_name}}][k4k8s-enterprise-install] +* [Database-backed installation with or without the {{site.kic_product_name}}](/gateway/{{page.release}}/install-and-run/helm/) + +### Migrating to 2.1.x and up + +Existing users of the `kong-enterprise-k8s` image who want to use 2.1.x or later +should switch to the `kong-gateway` image. + +If you encounter issues after switching images, please +[contact Enterprise Support][support]. + +## DB-less versus database-backed deployments + +When using {{site.base_gateway}} with {{site.kic_product_name}}, the source +of truth for Kong's configuration is +the Kubernetes configuration in etcd: Kong's custom Kubernetes resources, +ingresses, and services provide the information necessary for the ingress +controller to configure Kong. This differs from Kong deployments that do not +use an ingress controller, where configuration in the database or DB-less +config file is the source of truth. + +In traditional deployments, Kong's database provides +a persistent store of configuration available to all Kong nodes to ensure +consistent proxy behavior across the cluster that is not affected by node +restarts. Because etcd provides this functionality in Kong for Kubernetes +deployments, it is not necessary to run an additional database, reducing +maintenance and infrastructure requirements. + +While running {{site.base_gateway}} with {{site.kic_product_name}} +does not require a database, it is fully compatible +with PostgreSQL and requires it for some features. etcd still remains the +source of truth in database-backed deployments: the controller translates +Kubernetes resources from etcd into Kong configuration and inserts them into +the database via the Admin API. + +## Choosing between DB-less or database-backed deployments + +In general, DB-less deployments are simpler to maintain and require less +resources to run. +These deployments must set `KONG_DATABASE=off` in their environment variables. + +Database-backed deployments offer a wider range of features. Review the +sections below to determine if your use case requires a feature that is not +available in DB-less deployments. + +### Feature availability + +Some Enterprise features are not available in DB-less deployments. +Use a database-backed deployment if you want to use: + +* Dev Portal +* Teams (RBAC) +* Workspaces + +The following features have support in DB-less mode, but +work differently than in DB-backed modes: + +* Kong Manager (read-only) +* Vitals (using [Prometheus][vitals-prometheus] or [InfluxDB][vitals-influxdb] + strategies) + +When {{site.base_gateway}} is configured by the ingress controller, some +functionality in these features is different from traditional deployments: + +* Instead of using Kong Manager, proxy configuration is managed by the + controller, and you provide configuration via Kubernetes resources. +* Because the controller creates proxy configuration on behalf of users, you do + not need to interact with the Admin API directly. Kong's own RBAC + implementation isn't required for typical Kong for Kubernetes deployments, as + they do not expose the Admin API; only the controller can access it. + Kubernetes-level RBAC rules and namespaces should be used to restrict what + configuration administrators can create. +* Ingress controller instances create configuration in a single workspace only + (`default` by default). To use multiple workspaces, deploy + multiple controller instances, setting the `CONTROLLER_KONG_WORKSPACE` + environment variable to the workspace that instance should use. These + instances should set `CONTROLLER_INGRESS_CLASS` to unique values for each + instance to avoid creating duplicate configuration in workspaces. Note that + if controller instances are deployed outside the Kong pod the Admin API must + be exposed, and users should enable RBAC with workspace admin users for the + controllers. Set `CONTROLLER_KONG_ADMIN_TOKEN` to the RBAC user's token. +* The controller cannot manage configuration for features that require a + database: it cannot create workspaces, Dev Portal content, admins, etc. These + features must be configured manually through the Admin API or Kong Manager. + +### Plugin compatibility + +Not all plugins are compatible with DB-less operation. Review the +[list of supported plugins][supported-plugins] to see if you require a plugin +that needs a database. + +Third-party plugins are generally compatible with DB-less as long as they do +not create custom entities (i.e. they do not add new entities that users can +create and modify through the Admin API). + +### Manual configuration + +DB-less configuration must be supplied as a complete unit: it is not possible +to add or modify entities individually through the Admin API, or provide +partial configuration that is added to existing configuration. As such, all +configuration must be sourced from Kubernetes resources so that the ingress +controller can render it into a complete configuration. + +On database-backed deployments, users can create or modify configuration +through the Admin API. The ingress controller uses a tag (set by the +`CONTROLLER_KONG_ADMIN_FILTER_TAG` environment variable) to identify +configuration that it manages. While the controller will revert changes to +configuration with its tag, other configuration is left as-is. + +Although database-backed deployments can use controller-generated and +manually-added configuration simultaneously, Kong's recommended best practice +is to manage as much configuration through Kubernetes resources as possible. +Using both controller-managed and manual configuration can result in conflicts +between the two, and conflicts will prevent the controller from applying its +configuration. To minimize this risk: + +* Use the [admission webhook][admission-webhook] + to reject Kubernetes resources that conflict with other configuration, or are + otherwise invalid. +* Manually create configuration in a workspace that is not managed by the + controller. This avoids most conflicts, but not all: routes may still + conflict depending on your [route validation][route-validation] setting. + +Large numbers of consumers (and associated credentials) are the exception to +this rule: if your consumer count is in the tens of thousands, we recommend +that you create them and their credentials through the Admin API to reduce etcd +load. + +## Migrating between deployment types + +Because etcd is the source of truth for Kong's configuration, the ingress +controller can re-create Kong's proxy configuration even if the underlying +datastore changes. + +While most Kubernetes resources can be left unchanged when migrating between +deployment types, users must remove any KongPlugin resources that use +unavailable plugins when migrating from a database-backed deployment to a +DB-less deployment. No changes to Kubernetes resources are required if +migrating in the opposite direction. + +[enterprise-download]: https://hub.docker.com/r/kong/kong-gateway/ +[admission-webhook]: /kubernetes-ingress-controller/latest/deployment/admission-webhook +[route-validation]: /gateway/{{page.release}}/reference/configuration/#route_validation_strategy +[supported-plugins]:/kubernetes-ingress-controller/latest/references/plugin-compatibility +[k4k8s-enterprise-install]: /gateway/{{page.release}}/install-and-run/kubernetes +[k4k8s-with-enterprise-install]: /gateway/{{page.release}}/install-and-run/kubernetes +[vitals-prometheus]: /gateway/{{page.release}}/vitals/vitals-prometheus-strategy/ +[vitals-influxdb]: /gateway/{{page.release}}/vitals/vitals-influx-strategy/ +[support]: https://support.konghq.com/ diff --git a/app/gateway/2.7.x/plan-and-deploy/licenses/access-license.md b/app/gateway/2.7.x/plan-and-deploy/licenses/access-license.md new file mode 100644 index 000000000000..2a33c737898a --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/licenses/access-license.md @@ -0,0 +1,21 @@ +--- +title: Access Your Kong Gateway License +badge: enterprise +--- + +To enable Enterprise features, {{site.base_gateway}} requires a license file. +You will receive this file from Kong when you sign up for a +{{site.konnect_product_name}} Enterprise subscription. + +[Contact Kong](https://konghq.com/get-started) for more information. + +{:.note} +> **Note:** The free mode does not require a license. See +[{{site.base_gateway}} Licensing](/gateway/{{page.release}}/plan-and-deploy/licenses/) +for a feature comparison. + +Once a license has been deployed to a {{site.base_gateway}} node, retrieve it +using the [`/licenses` Admin API endpoint](/gateway/{{page.release}}/admin-api/licenses/examples/). + +If you have purchased a subscription but haven't received a license file, +contact your sales representative. diff --git a/app/gateway/2.7.x/plan-and-deploy/licenses/deploy-license.md b/app/gateway/2.7.x/plan-and-deploy/licenses/deploy-license.md new file mode 100644 index 000000000000..e87d3b3e86b8 --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/licenses/deploy-license.md @@ -0,0 +1,9 @@ +--- +title: Deploy an Enterprise License +badge: enterprise +--- + +Deploy an enterprise license to a {{site.base_gateway}} installation to gain access +to [Enterprise-specific features](/gateway/{{page.release}}/plan-and-deploy/licenses/). + +{% include_cached /md/enterprise/deploy-license.md heading="##" release=page.release %} diff --git a/app/gateway/2.7.x/plan-and-deploy/licenses/index.md b/app/gateway/2.7.x/plan-and-deploy/licenses/index.md new file mode 100644 index 000000000000..0160e564cd55 --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/licenses/index.md @@ -0,0 +1,111 @@ +--- +title: Kong Gateway Licensing +badge: enterprise +--- + +{{site.base_gateway}} can be used with or without a license. For Enterprise +functionality, {{site.base_gateway}} enforces the presence and validity of a +{{site.konnect_product_name}} license file. + +| Feature | Free Mode | Enterprise Subscription | +|--------------------|:---------:|:-----------------------:| +| Manager | | | +| Admin API | | | +| Vitals | | | +| Dev Portal | | | +| Enterprise plugins | | | + +## Deploying the license file + +License file checking is done independently by each node as the Kong process +starts. No network connectivity is necessary to execute the license validation process. + +There are multiple ways to configure a license file on a {{site.base_gateway}} +node. The method you use may depend on your deployment type. + +* **Hybrid mode deployment:** The license file must be deployed to +control plane nodes. The control planes then distribute the license to the data +planes in their clusters. Use the [`/licenses`](/gateway/{{page.release}}/admin-api/licenses/reference/) +endpoint to apply the license to the control plane. + +* **Traditional deployment with no separate control plane:** License files must +be deployed to each node running {{site.base_gateway}}. Use any of the +provided configuration methods to apply the license. + +Here are the possible license configuration methods, in the order that +{{site.base_gateway}} checks for them: + +1. If present, the contents of the environment variable `KONG_LICENSE_DATA` are used. +2. Kong will search in the default location `/etc/kong/license.json`. +3. If present, the contents of the file defined by the environment variable `KONG_LICENSE_PATH` is used. +4. Directly deploy a license using the `/licenses` Admin API endpoint. + +In this manner, the license file can be deployed either as a file on the node +filesystem, as an environment variable, or through the `/licenses` Admin API +endpoint. The simplest method is using the Admin API. + +Note that unlike most other `KONG_*` environment variables, the +`KONG_LICENSE_DATA` and `KONG_LICENSE_PATH` cannot be defined in-line as part +of any `kong` CLI commands. License file environment variables must be +exported to the shell in which the Nginx process will run, ahead of the `kong` +CLI tool. + +For more information, see [Deploy Your License](/gateway/{{page.release}}/plan-and-deploy/licenses/deploy-license/). + +## Examining the license data on a {{site.base_gateway}} node + +Retrieve license data using the Admin API's `/licenses` endpoint, or through +the Admin GUI in Kong Manager. + +## License expiration + +When a license expires, you will still have access to your {{site.base_gateway}} +and its configuration. Any Enterprise-specific features will be locked, and +the Admin API will not be accessible until the license is either renewed or the +subscription is downgraded to the free mode. + +In the event of a downgrade, the Admin API will be unlocked, but Enterprise +features such Dev Portal, Enterprise plugins, and others will no +longer be accessible. + +### License expiration logs + +{{site.base_gateway}} logs the license expiration date on the following schedule: +* 90 days before: `WARN` log entry once a day +* 30 days before: `ERR` log entry once a day +* At and after expiration: `CRIT` log entry once a day + +## Troubleshooting + +When a valid license file is properly deployed, license file validation is a transparent operation; no additional output or logging data is written or provided. If an error occurs when attempting to validate the license, or the license data is not valid, an error message will be written to the console and logged to the Kong error log, followed by the process quitting. Below are possible error messages and troubleshooting steps to take: + +`license path environment variable not set` +: Neither the `KONG_LICENSE_DATA` nor the `KONG_LICENSE_PATH` environment variables were defined, and no license file could be opened at the default license location (`/etc/kong/license.json`) + +`internal error` +: An internal error has occurred while attempting to validate the license. Such cases are extremely unlikely; contact Kong support to further troubleshoot. + +`error opening license file` +: The license file defined either in the default location, or using the `KONG_LICENSE_PATH` env variable, could not be opened. Check that the user executing the Nginx process (e.g., the user executing the Kong CLI utility) has permissions to read this file. + +`error reading license file` +: The license file defined either in the default location, or using the `KONG_LICENSE_PATH` env variable, could be opened, but an error occurred while reading. Confirm that the file is not corrupt, that there are no kernel error messages reported (e.g., out of memory conditions, etc). This is a generic error and is extremely unlikely to occur if the file could be opened. + +`could not decode license json` +: The license file data could not be decoded as valid JSON. Confirm that the file is not corrupt and has not been altered since you received it from Kong Inc. Try re-downloading and installing your license file from Kong Inc. +: If you still receive this error after reinstallation, contact Kong support. + +`invalid license format` +: The license file data is missing one or more key/value pairs. Confirm that the file is not corrupt and has not been altered since you received it from Kong Inc. Try re-downloading and installing your license file from Kong Inc. +: If you still receive this error after reinstallation, contact Kong support. + +`validation failed` +: The attempt to verify the payload of the license with the license's signature failed. Confirm that the file is not corrupt and has not been altered since you received it from Kong Inc. Try re-downloading and installing your license file from Kong Inc. +: If you still receive this error after reinstallation, contact Kong support. + +`license expired` +: The system time is past the license's `license_expiration_date`. + +`invalid license expiration date` +: The data in the `license_expiration_date` field is incorrectly formatted. Try re-downloading and installing your license file from Kong Inc. +: If you still receive this error after reinstallation, contact Kong support. diff --git a/app/gateway/2.7.x/plan-and-deploy/licenses/report.md b/app/gateway/2.7.x/plan-and-deploy/licenses/report.md new file mode 100644 index 000000000000..39bd3d87923f --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/licenses/report.md @@ -0,0 +1,110 @@ +--- +title: Monitor License Usage +badge: enterprise +--- + +Obtain information about your {{site.base_gateway}} deployment, including license usage and deployment information using the **License Report** module. Share this information with Kong to perform a health-check analysis of product utilization and overall deployment performance to ensure your organization is optimized with the best license and deployment plan for your needs. + +How the license report module works: +* The license report module manually generates a report containing usage and deployment data by sending a request to an endpoint, as defined below. +* Share this report with your Kong representative to perform an analysis of your deployment. + +What the license report module **does not** do: +* The license report module does not automatically generate a report or send any data to any Kong servers. +* The license report module does not track or generate any data other than the data that is returned in the response after you send a request to the endpoint. + +## Generate a License Report +Run the license report module and share the output information with your Kong representative for a deployment analysis. + +**Prerequisites**: You must have Admin privileges to generate a license report. + +To generate a license report, from an HTTP client: + +{% navtabs %} +{% navtab JSON response %} + +For a JSON response, send an HTTP request to the Kong node endpoint +`/license/report`. For example, use this cURL command: + +```bash +curl {ADMIN_API_URL}/license/report +``` + +A JSON response returns, similar to the example below: + +```json +HTTP/1.1 200 OK +Access-Control-Allow-Credentials: true +Access-Control-Allow-Origin: http://localhost:8002 +Connection: keep-alive +Content-Length: 814 +Content-Type: application/json; charset=utf-8 +Date: Mon, 06 Dec 2021 12:04:28 GMT +Server: kong/2.7.0.1-enterprise-edition +Vary: Origin +X-Kong-Admin-Request-ID: R1jmopI6fjkOLdOuPJVLEmGh4sCLMpSY +{ + "counters": [ + { + "bucket": "2021-09", + "request_count": 30 + }, + { + "bucket": "2020-10", + "request_count": 42 + }, + + { + "bucket": "2021-11", + "request_count": 296 + }, + { + "bucket": "2021-12", + "request_count": 58 + }, + { + "bucket": "UNKNOWN", + "request_count": 50 + } + ], + "db_version": "postgres 9.6.24", + "kong_version": "2.7.0.1-enterprise-edition", + "license_key": "KONGLICENSEKEY_NOTVALIDFORREAL_USAGE", + "rbac_users": 0, + "services_count": 27, + "system_info": { + "cores": 6, + "hostname": "akongnode", + "uname": "Linux x86_64" + }, + "workspaces_count":1 +} +``` + +{% endnavtab %} +{% navtab TAR file %} + +For a TAR file, enter the following cURL command to make a call to the +Kong Admin API: + +```bash +curl {ADMIN_API_URL}/license/report -o response.json && tar -cf report-$(date +"%Y_%m_%d_%I_%M_%p").tar response.json +``` + +A license report file is generated and archived to a `*.tar` file. + +{% endnavtab %} +{% endnavtabs %} + +## Report Structure + +Field | Description +------|------------ +`counters` | Counts the number of requests made in a given month.

    • `bucket`: Year and month when the requests were processed. If the value in `bucket` is `UNKNOWN`, then the requests were processed before {{site.base_gateway}} 2.7.0.1.
    • `request_count`: Number of requests processed in the given month and year. +`db_version` | The type and version of the datastore {{site.base_gateway}} is using. +`kong_version` | The version of the {{site.base_gateway}} instance. +`license_key` | An encrypted identifier for the current license key. If no license is present, the field displays as `UNLICENSED`. +`rbac_users` | The number of users registered with through RBAC. +`services_count` | The number of configured services in the {{site.base_gateway}} instance. +`system_info` | Displays information about the system running {{site.base_gateway}}.

    • `cores`: Number of CPU cores on the node
    • `hostname`: Encrypted system hostname
    • `uname`: Operating system +`workspaces_count` | The number of workspaces configured in the {{site.base_gateway}} instance. diff --git a/app/gateway/2.7.x/plan-and-deploy/performance-testing-framework.md b/app/gateway/2.7.x/plan-and-deploy/performance-testing-framework.md new file mode 100644 index 000000000000..5e344d6a8f5d --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/performance-testing-framework.md @@ -0,0 +1,352 @@ +--- +title: Performance Testing Framework +badge: oss +--- + +The {{site.base_gateway}} codebase includes a performance testing framework. It allows Kong developers and users to evaluate the performance of Kong itself as well as +bundled or custom plugins, and plot frame graphs to debug performance bottlenecks. +The framework collects RPS (request per second) and latencies of Kong processing the request +to represent performance metrics under different workloads. + +The framework is implemented as an extension to Kong's integration test suite. + +## Installation + +The framework uses [busted](https://github.com/lunarmodules/busted) and some +Lua development dependencies of Kong. To set up the environment, +run `make dev` on your Kong repository to install all Lua dependencies. + +## Drivers + +Three "drivers" are implemented depending on different environments, accuracy +requirements, and setup complexity. + +| Driver | Test between git commits | Test between binary releases | Flamegraph | Test unreleased version | +|----------|--------------------------|------------------------------|------------|-------------------------| +| local | yes | | yes | yes | +| docker | yes | yes | | | +|terraform | yes | yes | yes | | + +- **local** Driver reuses users' local environment. It's faster to run, +but the RPS and latency number may be influenced by other local programs and thus inaccurate. + + * Requires Lua development dependencies of Kong, OpenResty, and `wrk` be installed. + * Requires SystemTap, kernel headers, and build chain to be installed if generating FlameGraph. + +- **docker** Driver is solely based on Docker images. It's the most convenient driver to setup +as it requires less dependencies. But it may also be influenced by other local programs +and Docker network performance. And it doesn't support FlameGraph generation. + +- **terraform** Driver runs in remote VM or bare metal machine. It's most accurate, +but it requires Terraform knowledge to operate and setup. + + * Requires the [Terraform](https://www.terraform.io/downloads.html) binary be installed. + * Requires git binary if testing between git commits. When testing between git commits, + the framework assumes the current directory is Kong's repo. It will stash your working + directory and unstash after test is finished. When using the docker or terraform driver, + the framework derives the base version of each commit and uses the matching Docker image or + Kong binary package and puts local source code inside. + +## Workflow + +Like Kong's integration tests, the performance test is written in Lua. Several +test cases can share the same Lua file. + +The following code snippet demonstrates a basic workflow for defining a workload and load testing Kong. + +```lua +local perf = require("spec.helpers.perf") + +perf.use_driver("docker") + +local versions = { "git:master", "2.4.0" } + +for _, version in ipairs(versions) do + describe("perf test for Kong " .. version .. " #simple #no_plugins", function() + local bp + lazy_setup(function() + local helpers = perf.setup() + + bp = helpers.get_db_utils("postgres", { + "routes", + "services", + }) + + local upstream_uri = perf.start_upstream([[ + location = /test { + return 200; + } + ]]) + + local service = bp.services:insert { + url = upstream_uri .. "/test", + } + + bp.routes:insert { + paths = { "/s1-r1" }, + service = service, + strip_path = true, + } + end) + + before_each(function() + perf.start_kong(version, { + --kong configs + }) + end) + + after_each(function() + perf.stop_kong() + end) + + lazy_teardown(function() + perf.teardown() + end) + + it("#single_route", function() + local results = {} + for i=1,3 do + perf.start_load({ + path = "/s1-r1", + connections = 1000, + threads = 5, + duration = 10, + }) + + ngx.sleep(10) + + local result = assert(perf.wait_result()) + + print(("### Result for Kong %s (run %d):\n%s"):format(version, i, result)) + results[i] = result + end + + print(("### Combined result for Kong %s:\n%s"):format(version, assert(perf.combine_results(results)))) + + perf.save_error_log("output/" .. version:gsub("[:/]", "#") .. "-single_route.log") + end) + end) +end +``` + +The test can be run as a normal busted-based test. Run it with `bin/busted path/to/this_file_spec.lua`. + +More examples can be found in the [spec/04-perf](https://github.com/Kong/kong/tree/master/spec/04-perf) folder in the Kong +repository. + +## Sample Output + +``` +### Result for Kong git:96326b894f712b5d03bb1bf7ac02d531f6128cd1 (run 1): +Running 10s test @ http://10.88.145.9:8000/s1-r1 + 5 threads and 1000 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 17.51ms 61.46ms 1.04s 98.99% + Req/Sec 14.31k 2.61k 20.80k 82.59% + 672831 requests in 10.07s, 154.07MB read + Socket errors: connect 0, read 0, write 0, timeout 246 +Requests/sec: 66803.45 +Transfer/sec: 15.30MB +### Result for Kong git:96326b894f712b5d03bb1bf7ac02d531f6128cd1 (run 2): +Running 10s test @ http://10.88.145.9:8000/s1-r1 + 5 threads and 1000 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 14.71ms 10.66ms 96.77ms 66.18% + Req/Sec 14.45k 1.79k 20.19k 70.80% + 718942 requests in 10.08s, 164.70MB read +Requests/sec: 71337.25 +Transfer/sec: 16.34MB +### Result for Kong git:96326b894f712b5d03bb1bf7ac02d531f6128cd1 (run 3): +Running 10s test @ http://10.88.145.9:8000/s1-r1 + 5 threads and 1000 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 14.47ms 10.13ms 82.81ms 66.57% + Req/Sec 14.60k 1.64k 22.98k 72.00% + 726452 requests in 10.07s, 166.42MB read +Requests/sec: 72141.41 +Transfer/sec: 16.53MB +### Combined result for Kong git:96326b894f712b5d03bb1bf7ac02d531f6128cd1: +RPS Avg: 70094.04 +Latency Avg: 15.52ms Max: 1040.00ms +``` + +With samples in [spec/04-perf](https://github.com/Kong/kong/tree/master/spec/04-perf), the RPS and latency +results, Kong error logs and FlameGraph files are saved to `output` directory under current directory. + +## API + +### `perf.use_driver` + +*syntax: perf.use_driver(name, options?)* + +Uses driver name, which must be one of "local", "docker" or "terraform". Additional +parameters for the driver can be specified in options as a Lua table. Throws error if any. + +Only the terraform driver expects an options parameter, which contains following keys: + +- **provider** The service provider name, right now only "equinix-metal". +- **tfvars** Terraform variables as a Lua table; for `equinix-metal` provider, +`packet_project_id` and `packet_auth_token` is required. + +### `perf.set_log_level` + +*syntax: perf.set_log_level(level)* + +Sets the log level; expect one of `"debug"`, `"info"`, `"notice"`, `"warn"`, `"error"` and +`"crit"`. The default log level is `"info"`. + +### `perf.set_retry_count` + +*syntax: perf.set_retry_count(count)* + +Sets retry time for each “driver" operation. By default every operation is retried 3 times. + +### `perf.setup` + +*syntax: helpers = perf.setup()* + +Prepares environment and returns the `spec.helpers` module. Throws error if any. + +The framework sets up some environment variables before importing `spec.helpers` modules. +The returned helper is just a normal `spec.helpers` module. Users can use the same pattern +in integration tests to setup entities in Kong. DB-less mode is currently not implemented. + +### `perf.start_upstream` + +Syntax: +``` +upstream_uri = perf.start_upstream(nginx_conf_blob) +``` + +Starts upstream (Nginx/OpenResty) with given `nginx_conf_blob`. Returns the upstream +URI accessible from Kong's view. Throws error if any. + +### `perf.start_kong` + +Syntax: +``` +perf.start_kong(version, kong_configs?) +``` + +Starts Kong with given version and Kong configurations in `kong_configs` as a Lua table. +Throws error if any. + +To select a git hash or tag, use `"git:"` as version. Otherwise, the framework +will treat the `version` as a release version and will download binary packages from +Kong's distribution website. + +### `perf.stop_kong` + +Syntax: +``` +perf.stop_kong() +``` + +Stops Kong. Throws error if any. + +### `perf.teardown` + +Syntax: +``` +perf.teardown(full?) +``` + +Teardown. Throws error if any. With the terraform driver, setting full to true terminates +all infrastructure, while by default it does cleanup only to speed up successive runs. + +### `perf.start_stapxx` + +Syntax: +``` +perf.start_stapxx(stapxx_file_name, arg?) +``` + +Starts the Stap++ script with `stapxx_file_name` exists in +[available stapxx scripts](https://github.com/Kong/stapxx/tree/kong/samples) +and additional CLI args. Throws error if any. + +This function blocks test execution until the `SystemTap` module is fully prepared and inserted into the +kernel. It should be called before `perf.start_load`. + +### `perf.start_load` + +Syntax: +``` +perf.start_load(options?) +``` + +Starts to send load to Kong using `wrk`. Throws error if any. Options is a Lua table that may contain the following: + +- **path** String request path; defaults to `/ `. +- **uri** Base URI exception path; defaults to `http://kong-ip:kong-port/`. +- **connections** Connection count; defaults to 1000. +- **threads** Request thread count; defaults to 5. +- **duration** Number of performance tests duration in seconds; defaults to 10. +- **script** Content of `wrk` script as string; defaults to nil. + +### `perf.wait_result` + +Syntax: +``` +result = perf.start_load(options?) +``` + +Waits for the load test to finish and returns the result as a string. Throws error if any. + +Currently, this function waits indefinitely, or until both `wrk` and Stap++ processes exit. + +### `perf.combine_results` + +Syntax: +``` +combined_result = perf.combine_results(results, …) +``` + +Calculates multiple results returned by `perf.wait_result` and returns their average and min/max. +Throws error if any. + +### `perf.generate_flamegraph` + +Syntax: +``` +perf.generate_flamegraph(path, title?) +``` + +Generates a FlameGraph with title and saves to path. Throws error if any. + +### `perf.save_error_log` + +Syntax: +``` +perf.save_error_log(path) +``` + +Saves Kong error log to path. Throws error if any. + +## Customization + +### Add new test suite + +All tests are stored in `spec/04-perf/01-rps` and `spec/04-perf/02-flamegraph` of the Kong repository. +Add a new file under one of the directories and put `#tags` in the test description. + +### Add new provider in terraform + +Users can use the terraform driver in most major service providers as long as +it's supported by Terraform. The following contracts are made between the framework and terraform module: + +The terraform files are stored in `spec/fixtures/perf/terraform/`. + +Two instances are provisioned, one for running Kong and another for running an upstream +and load (worker). A firewall allows bidirectional traffic between the two instances +and from the public internet. Both instances run Ubuntu 20.04/focal. + +An SSH key to login into both instances exists or will be created in +`spec/fixtures/perf/terraform//id_rsa`. The logged-in user has root privilege. + +The following are terraform output variables: + +- **kong-ip** Kong node public IP. +- **kong-internal-ip** Kong node internal IP (if unavailable, provide kong-ip). +- **worker-ip** Worker node public IP. +- **worker-internal-ip** Worker node internal IP (if unavailable, provide worker-ip). diff --git a/app/gateway/2.7.x/plan-and-deploy/security/db-encryption.md b/app/gateway/2.7.x/plan-and-deploy/security/db-encryption.md new file mode 100644 index 000000000000..1cfd5369067c --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/security/db-encryption.md @@ -0,0 +1,319 @@ +--- +title: Keyring and Data Encryption +badge: enterprise +--- + +{{site.base_gateway}} provides a mechanism to store sensitive data fields, such as consumer secrets, in an encrypted format within the database. This provides for encryption-at-rest security controls in a Kong cluster. + +This functionality provides transparent, symmetric encryption of sensitive data fields at rest. _Transparency_ refers to the fact that, when enabled, encryption/decryption of data is done on-the-fly by Kong immediately before writing/immediately after reading from the database. Responses generated by the Admin API containing sensitive fields continue to show data as plaintext, and runtime elements of Kong (such as plugins) that require access to sensitive fields do so transparently, without requiring additional configuration. + +## Getting Started + +This document provides a brief introduction to leveraging {{site.base_gateway}} symmetric database encryption to store sensitive configuration data in a Kong cluster. This document covers necessary Kong configuration settings and key management lifecycle procedures when using database encryption in `cluster` mode. This mode offers the simplest method to getting started, as it requires no external dependencies. + +### Generate a Management RSA Key Pair + +Before enabling database encryption, we strongly recommend you generate an RSA key pair for use in exporting and recovering keyring material. If keyring material is lost, it is impossible to recover any sensitive data fields written to the database with a key on that keyring. + +Generating an RSA key pair is straightforward via the `openssl` CLI: + +```bash +$ openssl genrsa -out key.pem 2048 +$ openssl rsa -in key.pem -pubout -out cert.pem +``` + +This key pair will be provided to Kong in order to facilitate exporting and re-importing the keyring. The public `cert.pem` and private `key.pem` should be stored securely in accordance with your existing secrets management policies. Details on secure storage of RSA key pairs is outside the scope of this documentation. + +### Configure Kong for database encryption + +Enabling data encryption in Kong requires modifying the Kong configuration. Set the following values in `kong.conf`: + +``` +keyring_enabled = on +keyring_strategy = cluster +keyring_public_key = /path/to/generated/cert.pem +keyring_private_key = /path/to/generated/key.pem +``` + +Or via environmental variables: + +``` +export KONG_KEYRING_ENABLED=on +export KONG_KEYRING_STRATEGY=cluster +export KONG_KEYRING_PUBLIC_KEY=/path/to/generated/cert.pem +export KONG_KEYRING_PRIVATE_KEY=/path/to/generated/key.pem +``` + +All nodes in the Kong cluster should share the same `keyring_enabled` and `keyring_strategy` configuration values. Not every node needs to be provided the management RSA key pair, as that key pair is only used for backup and recovery processes. It does not need to be present for regular database read/write operations. + +Note that the user under which Kong worker processes run must have read access to the public and private keys in order to be able to perform keyring export and import operations. This user is defined by the `nginx_user` Kong configuration option. We recommend restricting access to these files as tightly as possible. For example: + +```bash +$ chown : /path/to/generated/cert.pem /path/to/generated/key.pem +$ chmod 400 /path/to/generated/cert.pem /path/to/generated/key.pem +``` + +When testing, you can also set `keyring_blob_path` in kong.conf or `KONG_KEYRING_BLOB_PATH` +using environmental variables to specify a path to dump known keys. The dumped keys are +encrypted with the public RSA key defined in the `keyring_public_key` Kong configuration +value, and are automatically loaded during Kong start. + +### Start Kong + +Once all Kong nodes in the cluster have been configured, start each node: + +```bash +$ kong start +``` + +When encryption is enabled on a Kong node, it checks the status of the cluster keyring on boot. If it detects that no keys are present in the keyring, it will generate a key automatically. This process allows encryption/decryption operations to begin immediately. + +For all other nodes, the generated key will be automatically distributed within a few seconds. + +Note that encryption keys are held _only_ in memory, and do not persist past a restart of the Kong process (e.g., running `kong restart`). Because of this limitation, you must export the keyring following its initialization. Otherwise, if all Kong nodes in a cluster restart simultaneously, any sensitive fields written with the keyring become unrecoverable. Key material still persists after a soft reload of Kong (i.e., `kong reload`). + +### Verify the Cluster Keyring + +With the keyring enabled and Kong started, verify the contents of the keyring: + + +```bash +$ curl -s localhost:8001/keyring | jq +{ + "ids": [ + "LaW1urRQ" + ], + "active": "LaW1urRQ" +} +``` + +Note that in this example, the value `LaW1urRQ` is the _ID_ of the key, not the key material itself. + +### Export the Keyring + +Before going further, export the keyring. The exported material can be re-imported to the cluster in the event of an outage, or to restore a previously-deleted key: + +```bash +$ curl -XPOST -s localhost:8001/keyring/export | jq +{ + "data": "eyJrIjoiV1JZeTdubDlYeFZpR3VVQWtWTXBcL0JiVW1jMWZrWHluc0dKd3N4M1c0MlIxWE5XM05lZ05sdFdIVmJ1d0ZnaVZSTnFSdmM1WERscGY3b0NIZ1ZDQ3JvTFJ4czFnRURhOXpJT0tVV0prM2lhd0VLMHpKTXdwRDd5ZjV2VFYzQTY0Y2UxcVl1emJoSTI4VUZ1ZExRZWljVjd2T3BYblVvU3dOY3IzblhJQWhyWlcxc1grWXE3aHM1RzhLRXY2OWlRamJBTXAwbHZmTWNFWWxTOW9NUjdnSm5xZWlST0J1Q09iMm5tSXg0Qk1uaTJGalZzQzBtd2R2dmJyYWxYa3VLYXhpRWZvQm9EODk3MEtVcDYzY05lWGdJclpjang4YmJDV1lDRHlEVmExdGt5c0g1TjBJM0hTNDRQK1dyT2JkcElCUk5vSVZVNis1QWdcLzdZM290RUdzN1E9PSIsImQiOiIxWEZJOXZKQ05CTW5uVTB5c0hQenVjSG5nc2c5UURxQmcxZ3g1VVYxNWNlOEVTTlZXTmthYm8zdlUzS2VRTURcL0RUYXdzZCtJWHB5SllBTkRtanZNcytqU2lrVTFiRkpyMEVcLzBSRlg2emJrT0oybTR2bXlxdVE9PSIsIm4iOiJUUmRLK01Qajh6MkdHTmtyIn0=" +} + +``` + +The response generated is an opaque blob containing the keyring, encrypted with +a randomly-generated symmetric key. This random key is encrypted with the public +RSA key defined via the `keyring_public_key` Kong configuration value. + +The exported keyring should be stored in a safe location for disaster recovery +purposes. It is not designed to be modified or decrypted before being used during +a disaster recovery process. + +### Exercise the Encryption Routines + +Create a Consumer with a basic-auth credential. At this point, the `password` field of the basic-auth credential will be symmetrically encrypted before it is written to the database (in addition to being hashed by the basic-auth plugin, which is done by the plugin regardless of whether keyring encryption is enabled): + +```bash +$ curl -s localhost:8001/consumers -d username=bob | jq +{ + "custom_id": null, + "created_at": 1576518610, + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9", + "tags": null, + "username": "bob", + "type": 0 +} +``` + +```bash +$ curl -s localhost:8001/consumers/bob/basic-auth -d username=bob -d password=supersecretpassword | jq +{ + "created_at": 1576518704, + "consumer": { + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9" + }, + "id": "fc46ce48-c1d6-4078-9f51-5a777350a8a2", + "password": "da61c0083b6d19ef3db2490d0da96a71572da0fa", + "username": "bob" +} +``` + +Note that the returned `password` field in the API response is not the encrypted value; database encryption does not modify responses generated by the Admin API. This allows existing workflows to continue in the same form, while providing encryption at rest security under the hood. We can verify this by examining the value stored in the database: + +``` +kong=# select id,password from basicauth_credentials; + id | password +--------------------------------------+--------------------------------------------------------------------------------------------------------------------------- + fc46ce48-c1d6-4078-9f51-5a777350a8a2 | $ke$1$-LaW1urRQ-0f5b1ee8ddeefca1a1d75125-53f158a5f619133a2113692a7057e2b91fa947321de4480d452dd42c36bc9ef8aa6499cd429db6d7 +(1 row) +``` + +We can also verify that reading back the credential after it has been created behaves as expected: + +```bash +$ curl -s localhost:8001/consumers/bob/basic-auth/fc46ce48-c1d6-4078-9f51-5a777350a8a2 | jq +{ + "created_at": 1576518704, + "consumer": { + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9" + }, + "id": "fc46ce48-c1d6-4078-9f51-5a777350a8a2", + "password": "da61c0083b6d19ef3db2490d0da96a71572da0fa", + "username": "bob" +} +``` + +### Exercise Importing the Keyring + +Restart Kong and re-import the previously exported keyring: + +```bash +$ kong restart +``` + +```bash +$ curl localhost:8001/keyring/import -d data= +``` + +This operation requires that the `keyring_private_key` point to the private RSA +key associated with the public key used during the initial keyring export. Once +this is complete, Admin API operations that require the keyring for encryption/ +decryption can be verified: + +```bash +$ curl -s localhost:8001/consumers/bob/basic-auth/fc46ce48-c1d6-4078-9f51-5a777350a8a2 | jq +{ + "created_at": 1576518704, + "consumer": { + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9" + }, + "id": "fc46ce48-c1d6-4078-9f51-5a777350a8a2", + "password": "da61c0083b6d19ef3db2490d0da96a71572da0fa", + "username": "bob" +} +``` + +### Rotating Key Material + +As noted above, Kong supports rotating keys by allowing for multiple keys to exist on the keyring at the same time. This allows for data fields written by one key to be read back, while a fresher encryption key is used for write operations. Rotating keys is a matter of importing or generating a new key into the keyring, and marking it as active. Arbitrary key material can be imported via the `/keyring/import` material, or Kong can generate a new key via `/keyring/generate` endpoint: + +```bash +$ curl -XPOST -s localhost:8001/keyring/generate +{ + "key": "t6NWgbj3g9cbNVC3/D6oZ2Md1Br5gWtRrqb1T2FZy44=", + "id": "8zgITLQh" +} +``` + +Note that as a convenience the raw key material is returned from this endpoint call. + +Once a new key is present in the keyring, activate the key's ID: + +```bash +$ curl -s localhost:8001/keyring/activate -d key=8zgITLQh +``` + +Kong can write new sensitive data fields with the current `active` key, and read previously written fields in the database with the prior key, provided that key is in the keyring. Kong automatically selects the appropriate key to use when decrypting fields from the database. + +At this point, it is encouraged to take another backup of the keyring via the `/keyring/export` Admin API endpoint. + +### Rotating Encrypted Data Fields + +Once the keyring has updated, existing encrypted fields can rotate to use the new active key. To accomplish this rotation, issue a PATCH request to the entity in question: + +```bash +$ # curl -XPATCH -s localhost:8001/consumers/bob/basic-auth/fc46ce48-c1d6-4078-9f51-5a777350a8a2 -d password=adifferentsecretpassword | jq +{ + "created_at": 1576518704, + "consumer": { + "id": "6375b5fd-9c95-4822-b2dd-80ffbccb7ec9" + }, + "id": "fc46ce48-c1d6-4078-9f51-5a777350a8a2", + "password": "cc7274e94e41f3e00c238ff8712d1a83693f2a89", + "username": "bob" +} +``` + +Again, note that the encryption behavior is transparent to the Admin API response. Under the hood, Kong reads the entity's `password` field with a read-only encryption key. As part of the PATCH process, Kong writes the `password` field back to the database with the new `active` key. To verify this process, examine the raw contents of the database: + +``` +kong=# select id,password from basicauth_credentials; + id | password +--------------------------------------+--------------------------------------------------------------------------------------------------------------------------- + fc46ce48-c1d6-4078-9f51-5a777350a8a2 | $ke$1$-8zgITLQh-b8d28531252241e6b95907e4-0768a9a4baaa2c777d9406d4e3098d813be55ae82c4c849182b06b9c5954704c6290c9e677bcd693 +(1 row) +``` + +Note that the key identifier within the password data blob has been updated. This rotation mechanism allows organizations to meet specific compliance needs around key management rotation and retention policies. + +Currently, encrypted fields must undergo a direct write operation in order to rotate the encrypted field. Future releases of Kong may contain helper API operations to automate this process. + +### Exploring Missing Keyring Material Behavior + +As a test, stop all Kong nodes in the cluster, and restart one Kong node again, but do not import the keyring material. The behavior of attempting to read an entity with an encrypted field now changes: + +```bash +$ time curl -s localhost:8001/consumers/bob/basic-auth/fc46ce48-c1d6-4078-9f51-5a777350a8a2 +{"message":"An unexpected error occurred"} +real 0m24.811s +user 0m0.017s +sys 0m0.006s +``` + +When the Kong node restarts, it sends a broadcast request for the keyring, but as no other nodes are present in the cluster (or no other nodes had the keyring available), Kong is unable to decrypt the `password` field on the credential. Because Kong has an eventually-consistent clustering model, it makes several attempts to request the keyring and allows for delays in hearing responses from another cluster node; thus, the request takes several seconds to complete before finally failing. + +## Implementation Details + +### Encryption/Decryption + +{{site.base_gateway}} uses 256-bit AES encryption in GCM mode. Cryptographic nonce values for each encryption routine execution are derived from the kernel CSPRNG (`/dev/urandom`). The AES routines used by Kong are provided by the OpenSSL library bundled with the {{site.base_gateway}} package. + +### Key Generation and Lifecycle + +{{site.base_gateway}}'s keyring handling mechanisms allow for more than one key to be present on any given Kong node at a time. Each key may be used to read encrypted fields from the database, but one and only one key at any given time is used to write encrypted fields back to the data store. This process allows for a key rotation mechanism wherein new keyring material is introduced, and older keys may be present for a time to allow rotating previously-encrypted fields. + +Through the kernel CSPRNG, Kong derives keyring material generated through the `/keyring/generate` Admin API endpoint. Kong stores keyring material in a shared memory zone that all Kong worker processes access. To prevent key material from being written to disk as part of memory paging operations, we recommend that swap be disabled on systems running Kong + +When operating in `cluster` mode, keyring material propagates automatically among all nodes in the Kong cluster. Because Kong nodes do not have a notion of direct peer-to-peer communication, the underlying datastore serves as a communication channel to transmit messages. When a Kong node starts, it generates an ephemeral RSA key pair. The node's public keys propagate to all other active nodes in the cluster. When an active node sees a message request for keyring material, it wraps the in-memory keyring material in the presented public key, and transmits the payload back over the central messaging channel provided by the underlying data store. This process allows each node in the cluster to broadcast keyring material to new nodes, without sending key material in plaintext over the wire. This model requires that at least one node be running at all times within the cluster; a failure of all nodes requires manually re-importing the keyring to one node during an outage recovery. + +### Encrypted Fields + +The keyring module encrypts the following fields at rest: + +* `key` fields of `certificate` objects (corresponding to the private key of a TLS certificate). +* Certain configuration parameters in plugins and plugin-related authentication +objects. For information on which plugin fields are encrypted, see +[each individual plugin's documentation](/hub/). + +## Vault Integration + +Kong's keyring mechanism can integrate directly with [HashiCorp Vault](https://www.vaultproject.io/) for keyring storage and versioning. In this model, Kong nodes read keyring material directly from a Vault KV secrets engine, rather than generating and disseminating keyring material around the cluster. + +To configure Kong to use Vault for keyring storage, set the `keyring_strategy` configuration value to `vault`. Leveraging Vault also requires defining a host, mount point, and token for Vault access. See the Kong configuration reference for more details. + +### Key Format + +Kong leverages version 2 of the [Vault KV secrets engine](https://www.vaultproject.io/docs/secrets/kv/kv-v2.html). This process allows for the same versioning and key rotation mechanisms that the `cluster` keyring strategy provides. Each version of a KV secrets entry must contain both an `id` field, and a `key` field, e.g.: + +```json +{ + "key": "t6NWgbj3g9cbNVC3/D6oZ2Md1Br5gWtRrqb1T2FZy44=", + "id": "8zgITLQh" +} +``` + +To provide consistent consumption of all Vault KV secrets, the underlying symmetric key is derived as the SHA256 of the `key` component of the secret value. Take note of this derivation when extending or re-using symmetric encryption keys from other systems. This derivation also implies that the `key` field can contain any arbitrary data, as Kong hashes the contents before importing the material into the keyring. + +To provide a new key, add a new version to the Vault secrets engine at the configured path. The `current_version` of the Vault secret denotes the active key in the keyring. See the [KV v2 documentation](https://www.vaultproject.io/docs/secrets/kv/kv-v2.html) for more detail. + +### Vault Permissions + +In order to communicate with Vault, Kong must be provided a Vault token for access. The token must be associated with a policy that allows the `read` and `list` actions on the path where keyring secrets are stored. Kong does not write keyring material to the Vault cluster. + +### Syncing the Keyring + +Kong reads the keyring material from Vault when the Kong process starts. Any changes to the Vault KV store are not reflected on the Kong node until Kong syncs with Vault via the `/keyring/vault/sync` Admin API endpoint. This allows Kong to receive a Vault token with a low TTL, as the list and read operation only occur once. + +### Keyring on hybrid mode + +Because Keyring encrypts the data in the database, it means it doesn't encrypt data on Kong data plane nodes that run without a database and get data from the control plane. diff --git a/app/gateway/2.7.x/plan-and-deploy/security/kong-security-update-process.md b/app/gateway/2.7.x/plan-and-deploy/security/kong-security-update-process.md new file mode 100644 index 000000000000..537a3b4f3604 --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/security/kong-security-update-process.md @@ -0,0 +1,19 @@ +--- +title: Kong Security Update Process +--- + +## Reporting a Vulnerability + +If you have found a vulnerability or a potential vulnerability in the Kong gateway or other Kong software, or know of a publicly disclosed security vulnerability, please immediately let us know by emailing [security@konghq.com](mailto:security@konghq.com). We'll send a confirmation email to acknowledge your report, and we'll send an additional email when we've identified the issue positively or negatively. + +Once a report is received, we will investigate the vulnerability and assign it a [CVSS](https://www.first.org/cvss/) score which will determine the timeline for the development of an appropriate fix. + +While the fix development is underway, we ask that you do not share or publicize an unresolved vulnerability with third parties. If you responsibly submitted a vulnerability report, we will do our best to acknowledge your report in a timely fashion and notify you of the estimated timeline for a fix. + +## Fix Development Process + +If a discovered vulnerability with a CVSS score above 4.0 (medium severity or higher) affects the latest major release of the Kong gateway or other Kong software, then we will work to develop a fix in the most timely fashion. The work and communication around the fix will happen in private channels, and a delivery estimate will be given to the vulnerability reporter. Once the fix is developed and verified, a new patch version will be released by Kong for each supported {{site.base_gateway}} release and for the current release of the open source gateway. We will disclose the vulnerability as appropriate. + +Discovered vulnerabilities with a CVSS score below 4.0 (low severity) will follow the same fix development and release process but with a less urgent timeline. + +Vulnerabilities affecting upstream projects (e.g. NGINX, OpenResty, OpenSSL...) will receive fixes as per the upstream project's disclosure timeline. diff --git a/app/gateway/2.7.x/plan-and-deploy/security/start-kong-securely.md b/app/gateway/2.7.x/plan-and-deploy/security/start-kong-securely.md new file mode 100644 index 000000000000..6a5b35a3ddb7 --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/security/start-kong-securely.md @@ -0,0 +1,99 @@ +--- +title: Start Kong Gateway Securely +badge: enterprise +--- + +To secure the Admin API or Kong Manager, a Super Admin account is +required. + +The Super Admin has the ability to invite other Admins and +restrict their access based on Permissions of Roles within +Workspaces. + +The first Super Admin account is created during database migrations +following the guide below. It may only be added once. + +## Prerequisites + +After [installing {{site.base_gateway}}](/gateway/{{page.release}}/install-and-run/), +either modify the configuration file or set environment variables for +the following properties: + +* `enforce_rbac` will force all Admin API requests to require a +`Kong-Admin-Token`. The Admin associated with the `Kong-Admin-Token` +must have adequate Permissions in order for the request to succeed. + +* If using Kong Manager, select the type of authentication that Admins +should use to log in. For the purpose of this guide, `admin_gui_auth` +may be set to `basic-auth`. See +[Securing Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/) for other types +of authentication. + +For a simple configuration to use for the subsequent Getting +Started guides: + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + +``` +enforce_rbac = on +admin_gui_auth = basic-auth +admin_gui_session_conf = {"secret":"secret","storage":"kong","cookie_secure":false} +admin_listen = 0.0.0.0:8001, 0.0.0.0:8444 ssl +``` + +⚠️**Important:** the Sessions Plugin requires a secret and is configured securely by default. +* Under all circumstances, the `secret` must be manually set to a string. +* If using HTTP instead of HTTPS, `cookie_secure` must be manually set to `false`. +* If using different domains for the Admin API and Kong Manager, `cookie_samesite` must be set to `off`. +Learn more about these properties in [Session Security in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#session-security), and see [example configurations](/gateway/{{page.release}}/configure/auth/kong-manager/sessions/#example-configurations). + +## Step 1 + +Set a password for the Super Admin. This environment variable must +be present in the environment where database migrations will run. + +{:.important} +> **Important**: Setting your Kong password (`KONG_PASSWORD`) using a value containing four ticks (for example, `KONG_PASSWORD="a''a'a'a'a"`) causes a PostgreSQL syntax error on bootstrap. To work around this issue, do not use special characters in your password. + +``` +$ export KONG_PASSWORD= +``` + +This automatically creates a user, `kong_admin`, and a password that +can be used to log in to Kong Manager. This password may also be +used as a `Kong-Admin-Token` to make Admin API requests. + +**Note:** only one Super Admin may be created using this method, and only +on a fresh installation with an empty database. If one is not created during migrations, +follow [this guide](/gateway/{{page.release}}/configure/auth/rbac/add-admin/) to remediate. + +Future migrations will not update the password or create additional Super Admins. +To add additional Super Admins it is necessary to +[invite a new user as a Super Admin in Kong Manager](/gateway/{{page.release}}/configure/auth/kong-manager/super-admin/). + +## Step 2 + +Issue the following command to prepare your data store by running the Kong migrations: + +``` +$ kong migrations bootstrap [-c /path/to/kong.conf] +``` + +## Step 3 + +Start Kong: + +``` +$ kong start [-c /path/to/kong.conf] +``` + +**Note:** the CLI accepts a configuration option (`-c /path/to/kong.conf`) +allowing you to point to [your own configuration](/gateway/{{page.release}}/reference/configuration/#configuration-loading). + +## Step 4 + +To test that {{site.base_gateway}} has successfully started with a Super Admin, +visit Kong Manager's URL. By default, it is on port `:8002`. + +The username is `kong_admin` and the password is the one set in +[Step 1](#step-1). diff --git a/app/gateway/2.7.x/plan-and-deploy/sizing-guidelines.md b/app/gateway/2.7.x/plan-and-deploy/sizing-guidelines.md new file mode 100644 index 000000000000..1b94979c2162 --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/sizing-guidelines.md @@ -0,0 +1,190 @@ +--- +title: Resource Sizing Guidelines +--- + +This document discusses the performance characteristics of +{{site.base_gateway}}, and offers recommendations on sizing for +resource allocation based on expected {{site.base_gateway}} configuration and +traffic patterns. + +These recommendations are a baseline guide only. Specific tuning or +benchmarking efforts should be undertaken for performance-critical environments. + +## General resource guidelines + +### {{site.base_gateway}} resources + +{{site.base_gateway}} is designed to operate in a variety of deployment +environments. It has no minimum system requirements to operate. + +Resource requirements vary substantially based on configuration. The following +high-level matrices offer a guideline for determining system requirements +based on overall configuration and performance requirements. + +Consider the following simplified examples, where latency and throughput requirements are considered on a per-node basis. This table has rough usage requirement estimates: + +| Size | Number of Configured Entities | Latency Requirements | Throughput Requirements | Usage Pattern | +|---|---|---|---|---| +| Small | < 100 | < 100 ms | < 500 RPS | Dev/test environments; latency-insensitive gateways | +| Medium | < 1000 | < 20 ms | < 2500 RPS | Production clusters; greenfield traffic deployments | +| Large | < 10000 | < 10 ms | < 10000 RPS | Mission-critical clusters; legacy & greenfield traffic; central enterprise-grade gateways | + +### Database resources + +We do not provide any hard numbers for database sizing (DB sizing), as it +depends on your particular setup. Sizing varies based on: +* Traffic +* Number of nodes +* Enabled features: for example, Vitals, or if rate limiting uses a +database or Redis +* Number and rate of change of configured entities +* The rate at which {{site.base_gateway}} processes are started and restarted within the cluster +* The size of {{site.base_gateway}}'s [in-memory cache](#in-memory-caching) + +{{site.base_gateway}} intentionally relies on the database as little as +possible. To access configuration, {{site.base_gateway}} executes a spiky +access pattern to its backing database. This means that {{site.base_gateway}} +only reads configuration from the database when a node first starts, or +configuration for a given entity changes. + +Everything in the database is meant to be read infrequently and held in memory +as long as possible. Therefore, database resource requirements are lower than +those of compute environments running {{site.base_gateway}}. + +Query patterns are typically simple and follow schema indexes. Provision +sufficient database resources in order to handle spiky query patterns. + +There are [settings](/gateway/{{page.release}}/reference/configuration/#datastore-section/) +that you can adjust to keep database access minimal (also see [in-memory caching](#in-memory-caching)), or +[keep {{site.base_gateway}} operational](https://support.konghq.com/support/s/article/Keeping-Kong-Functional-During-DB-Down-Times) +if the DB is down for maintenance. If you choose to keep the database +operational during downtimes, vitals data is not written to the +database during this time. + +### Cluster resource allocations + +Based on the expected size and demand of the cluster, we recommend +the following resource allocations as a starting point: + +| Size | CPU | RAM | Typical Cloud Instance Sizes | +|---|---|---|---|---| +| Small | 1-2 cores | 2-4 GB | **AWS**: t3.medium
    **GCP**: n1-standard-1
    **Azure**: Standard A1 v2 | +| Medium | 2-4 cores | 4-8 GB | **AWS**: m5.large
    **GCP**: n1-standard-4
    **Azure**: Standard A1 v4 | +| Large | 8-16 cores | 16-32 GB | **AWS**: c5.xlarge
    **GCP**: n1-highcpu-16
    **Azure**: F8s v2 | + +We strongly discourage the use of throttled cloud instance types (such as the +AWS `t2` or `t3` series of machines) in large clusters, as CPU throttling would +be detrimental to {{site.base_gateway}}'s performance. We also recommend +testing and verifying the bandwidth availability for a given instance class. +Bandwidth requirements for {{site.base_gateway}} depend on the shape and volume +of traffic flowing through the cluster. + +### In-memory caching +We recommend defining the `mem_cache_size` configuration as large as possible, +while still providing adequate resources to the operating system and any other +processes running adjacent to {{site.base_gateway}}. This configuration allows +{{site.base_gateway}} to take maximum advantage of the in-memory cache, and +reduce the number of trips to the database. + +Each {{site.base_gateway}} worker process maintains its own memory allocations, +and must be accounted for when provisioning memory. By default, one worker +process runs per number of available CPU cores. We recommend allowing for +around **500MB** of memory allocated per worker process. + +For example, on a machine with 4 CPU cores and 8 GB of RAM available, we recommend allocating between 4-6 GB to cache via the `mem_cache_size` directive, depending on what other processes are running alongside {{site.base_gateway}}. + +## Scaling dimensions + +{{site.base_gateway}} is designed to handle large volumes of request +traffic and proxying requests with minimal latency. Understanding how various +configuration scenarios impacts request traffic, and the {{site.base_gateway}} +cluster itself, is a crucial step in successfully deploying +{{site.base_gateway}}. + +{{site.base_gateway}} measures performance in the following dimensions: + +* **Latency** refers to the delay between the downstream client +sending a request and receiving a response. {{site.base_gateway}} measures +latency introduced into the request in terms of microseconds or milliseconds. +Increasing the number of Routes and Plugins in a {{site.base_gateway}} cluster +increases the amount of latency that's added to each request. +* **Throughput** refers to the number of +requests that {{site.base_gateway}} can process in a given time span, typically +measured in seconds or minutes. + +These dimensions have an inversely proportional relationship +when all other factors remain the same: decreasing the latency introduced into +each request allows the maximum throughput in {{site.base_gateway}} to +increase, as there is less CPU time spent handling each request, and more +CPU available for processing traffic as a whole. {{site.base_gateway}} is +designed to scale horizontally to be able to add more overall compute power for +configurations that add substantial latency into requests, while needing to +meet specific throughput requirements. + +{{site.base_gateway}}'s maximum throughput is a CPU-bound dimension, and minimum +latency is memory-bound. +* **Latency-sensitive workload**: making more memory available for database caching +is more beneficial than adding more compute power to the cluster. +* **Throughput-sensitive workload**: these workloads are dependant on both adequate +memory and CPU resources, but adding more +compute power by scaling {{site.base_gateway}} vertically or horizontally is +the better choice, as it provides near-unlimited throughput capacity. In this +scenario, adding more cache memory would not increase maximum throughput by +much. + +Performance benchmarking and optimization as a whole is a complex exercise that +must account for a variety of factors, including those external to +{{site.base_gateway}}, such as the behavior of upstream services, or the health +of the underlying hardware on which {{site.base_gateway}} is running. + +## Performance characteristics + +There are a number of factors that impact {{site.base_gateway}}'s performance, +including: + +* **Number of configured Routes and Services**: Increasing the count of Routes +and Services on the cluster requires more CPU to evaluate the request. +However, {{site.base_gateway}}'s request router can handle running at large +scale. We've seen clusters of {{site.base_gateway}} nodes serving tens of +thousands of Routes with minimal impact to latency as a result of request route +evaluation. + +* **Number of configured Consumers and Credentials**: Consumer and credential +data is stored in {{site.base_gateway}}'s datastore. {{site.base_gateway}} +caches this data in memory to reduce database load and +latency during request processing. Increasing the count of Consumers and +Credentials requires more memory available for {{site.base_gateway}} to hold +data in cache. If there is not enough memory available to cache all requested +database entities, request latency increases as {{site.base_gateway}} needs to +query the database more frequently to satisfy requests. + +* **Number of configured Plugins**: Increasing the count of Plugins on the +cluster requires more CPU to iterate through plugins during request +processing. Executing plugins comes with a varying cost depending on the nature +of the plugin. For example, a lightweight authentication plugin like `key-auth` +requires less resource availability than a plugin that performs complex +transformations of an HTTP request or response. + +* **Cardinality of configured Plugins**: _Cardinality_ is the number +of distinct plugin types that are configured on the cluster. For example, a +cluster with one each of `ip-restriction`, `key-auth`, `bot-detection`, +`rate-limiting`, and `http-log` plugins has a higher plugin cardinality than a +cluster with one thousand `rate-limiting` plugins applied at the route level. +With each additional plugin type added to the cluster, {{site.base_gateway}} +spends more time evaluating whether to execute a given plugin for a given +request. Increasing the cardinality of configured plugins requires more CPU +power, as the process to evaluate plugins is a CPU-constrained task. + +* **Request and response size**: Requests with large HTTP bodies, either in the +request or response, take longer to process, as {{site.base_gateway}} must +buffer the request to disk before proxying it. This allows +{{site.base_gateway}} to handle a large volume of traffic without running out +of memory, but the nature of buffered requests can result in increased latency. + +* **Number of configured Workspaces**: Increasing the count of Workspaces on the +cluster requires more CPU to evaluate each request, and more memory +available for the cache to hold Workspace configuration and metadata. The +impact of increasing the number of Workspaces on the cluster is also affected +by the cardinality of configured plugins on the cluster. There is an +exponential impact on request throughput capacity within the cluster +as the cardinality of plugins _and_ the number of Workspaces increases. diff --git a/app/gateway/2.7.x/plan-and-deploy/systemd.md b/app/gateway/2.7.x/plan-and-deploy/systemd.md new file mode 100644 index 000000000000..729b1f2cba9e --- /dev/null +++ b/app/gateway/2.7.x/plan-and-deploy/systemd.md @@ -0,0 +1,153 @@ +--- +title: Control Kong Gateway through systemd +--- + +This document includes instructions on how to integrate {{site.base_gateway}} +with systemd for Debian and RPM based packages. + +Note that some of the supported GNU/Linux distributions for {{site.base_gateway}} +may not have adopted systemd as their default init system +(for example, CentOS 6 and RHEL 6). For the following instructions, it is +assumed that {{site.base_gateway}} has already been +[installed and configured](/gateway/{{page.release}}/install-and-run) on a +systemd-supported GNU/Linux distribution. + +## systemd commands for working with {{site.base_gateway}} + +### Start {{site.base_gateway}} + +```bash +# For {{site.base_gateway}} +sudo systemctl start kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl start kong +``` + +### Stop {{site.base_gateway}} + +```bash +# For {{site.base_gateway}} +sudo systemctl stop kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl stop kong +``` + +### Start {{site.base_gateway}} at system boot + +**Enable starting {{site.base_gateway}} automatically at system boot** + +```bash +# For {{site.base_gateway}} +sudo systemctl enable kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl enable kong +``` + +**Disable starting {{site.base_gateway}} automatically at system boot** + +```bash +# For {{site.base_gateway}} +sudo systemctl disable kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl disable kong +``` + +### Restart {{site.base_gateway}} + +```bash +# For {{site.base_gateway}} +sudo systemctl restart kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl restart kong +``` + +### Query {{site.base_gateway}} status + +```bash +# For {{site.base_gateway}} +sudo systemctl status kong-enterprise-edition + +# For {{site.ce_product_name}} +sudo systemctl status kong +``` + +## Customize the {{site.base_gateway}} unit file + +The official systemd service is located at `/lib/systemd/system/kong-enterprise-edition.service` for +{{site.base_gateway}}, or at `/lib/systemd/system/kong.service` for {{site.ce_product_name}}. + +For scenarios where customizations are needed (for example, configuring Kong +or modifying the service file behavior), we recommend creating another service +at `/etc/systemd/system/kong-enterprise-edition.service` for +{{site.base_gateway}}, or at `/etc/systemd/system/kong.service` for +{{site.ce_product_name}}, to avoid conflicts upon reinstalling or upgrading Kong. + +All environment variables prefixed with `KONG_` and capitalized will override the settings specified in the `/etc/kong/kong.conf.default` file. For example: `log_level = debug` in the .conf file translates to the `KONG_LOG_LEVEL=debug` environment variable. + +You can also choose use a configuration file instead of environment variables. In this case, modify the `ExecStartPre` systemd directive to execute `kong prepare` with the `-c` argument to point to your configuration file. For example, if you have a custom configuration file at `/etc/kong/kong.conf`, modify the `ExecStartPre` directive as follows: + +``` +ExecStartPre=/usr/local/bin/kong prepare -p /usr/local/kong -c /etc/kong/kong.conf +``` + +When linking non environment files using the `EnvironmentFile` systemd directive, note that the systemd parser will only recognize environment variables assignments. For example, if one of the Kong's default configuration files are linked (`/etc/kong/kong.conf.default` and `/etc/kong.conf`), non environment variables assignments in the file could lead to systemd errors. In this case, systemd will not allow the Kong service to be started. For this reason, we recommend specifying an `EnvironmentFile` other than the default ones: + +``` +EnvironmentFile=/etc/kong/kong_env.conf +``` + +### Logging to syslog and journald + +In this case, adding the below `Environment` systemd directives to your customized systemd service file at `/etc/systemd/system/kong-enterprise-edition.service` will do it: + +``` +Environment=KONG_PROXY_ACCESS_LOG=syslog:server=unix:/dev/log +Environment=KONG_PROXY_ERROR_LOG=syslog:server=unix:/dev/log +Environment=KONG_ADMIN_ACCESS_LOG=syslog:server=unix:/dev/log +Environment=KONG_ADMIN_ERROR_LOG=syslog:server=unix:/dev/log +``` + +To view the journald logs: + +```bash +# For {{site.base_gateway}} +journalctl -u kong-enterprise-edition + +# For {{site.ce_product_name}} +journalctl -u kong +``` + +To view the syslog logs: + +```bash +tail -F /var/log/syslog +``` + +### Customize Kong's Nginx instance using the Nginx directive injection system + +To use the [injection system](/gateway/{{page.release}}/reference/configuration/#injecting-individual-nginx-directives) with environment variables, add the below `Environment` systemd directive to your custom service at `/etc/systemd/system/kong-enterprise-edition.service` ({{site.base_gateway}}) or `/etc/systemd/system/kong.service` ({{site.ce_product_name}}). Note the quoting rules defined by systemd to specify an environment variable containing spaces: + +``` +Environment="KONG_NGINX_HTTP_OUTPUT_BUFFERS=4 64k" +``` + +### Customize Kong's Nginx instance using --nginx-conf + +To use the [`--nginx-conf`](/gateway/{{page.release}}/reference/configuration/#custom-nginx-templates) argument, modify the `ExecStartPre` systemd directive to execute `kong prepare` with the `--nginx-conf` argument. For example, if you have a custom template at `/usr/local/kong/custom-nginx.template`, modify the `ExecStartPre` directive as follows: + +``` +ExecStartPre=/usr/local/bin/kong prepare -p /usr/local/kong --nginx-conf /usr/local/kong/custom-nginx.template +``` + +### Customize Kong's Nginx instance including files via the injected Nginx directives + +To [include files via the injected Nginx directives](/gateway/{{page.release}}/reference/configuration/#including-files-via-injected-nginx-directives) with environment variables, add the below `Environment` systemd directive to your custom service at `/etc/systemd/system/kong-enterprise-edition.service` ({{site.base_gateway}}) or `/etc/systemd/system/kong.service` ({{site.ce_product_name}}): + +``` +Environment=KONG_NGINX_HTTP_INCLUDE=/path/to/your/my-server.kong.conf +``` diff --git a/app/gateway/2.7.x/plugin-development/access-the-datastore.md b/app/gateway/2.7.x/plugin-development/access-the-datastore.md new file mode 100644 index 000000000000..4f3e013d18f3 --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/access-the-datastore.md @@ -0,0 +1,69 @@ +--- +title: Plugin Development - Accessing the Datastore +book: plugin_dev +chapter: 5 +--- + +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/). + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + +## 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. + 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 PostgreSQL) 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 = "httpbin", + url = "https://httpbin.konghq.com", +}) + +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). + +[Plugin Development Kit]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.7.x/plugin-development/admin-api.md b/app/gateway/2.7.x/plugin-development/admin-api.md new file mode 100644 index 000000000000..c421cc1edd3f --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/admin-api.md @@ -0,0 +1,168 @@ +--- +title: Plugin Development - Extending the Admin API +book: plugin_dev +chapter: 8 +--- + +{:.note} +> **Notes:** +> * This chapter assumes that you have a relative + knowledge of [Lapis](http://leafo.net/lapis/). +> * The Admin API extensions are available only + for HTTP plugins, not Stream plugins. + +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 +``` + +## Add 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. In this example, +the functions are provided by the `kong.api.endpoints` library. + +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. + +[Admin API]: /gateway/{{page.release}}/admin-api/ diff --git a/app/gateway/2.7.x/plugin-development/custom-entities.md b/app/gateway/2.7.x/plugin-development/custom-entities.md new file mode 100644 index 000000000000..39795665f7ba --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/custom-entities.md @@ -0,0 +1,677 @@ +--- +title: Plugin Development - Storing Custom Entities +book: plugin_dev +chapter: 6 +--- + +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.url}}), 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 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. + + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + + +If your plugin is intended to support both Cassandra and PostgreSQL, 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. + +## Add 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 + + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + +While Kong's core migrations support both PostgreSQL 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 PostgreSQL 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 PostgreSQL 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 PostgreSQL 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 PostgreSQL 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/master/kong/plugins/key-auth/migrations). + + +## Define 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`: + { + name = "keyauth_credentials", -- the actual table in the database + endpoint_key = "key", + primary_key = { "id" }, + cache_key = { "key" }, + generate_admin_api = true, + admin_api_name = "key-auths", + admin_api_nested_name = "key-auth", + 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. +
    generate_admin_apiboolean (optional) + Whether to auto-generate admin api for the entity or not. By default the admin api is generated for all + daos, including custom ones. If you want to create a fully customized admin api for the dao or + want to disable auto-generation for the dao altogether, set this option to false. +
    admin_api_nameboolean (optional) + When generate_admin_api is enabled the admin api auto-generator uses the name + to derive the collection urls for the auto-generated admin api. Sometimes you may want to name the + collection urls differently from the name. E.g. with DAO keyauth_credentials + we actually wanted the auto-generator to generate endpoints for this dao with alternate and more + url-friendly name key-auths, e.g. http://<KONG_ADMIN>/key-auths instead of + http://<KONG_ADMIN>/keyauth_credentials). +
    admin_api_nested_nameboolean (optional) + Similar to admin_api_name the admin_api_nested_name specifies the name for + a dao that admin api auto-generator creates in nested contexts. You only need to use this parameter + if you are not happy with name or admin_api_name. Kong for legacy reasons + have urls like http://<KONG_ADMIN>/consumers/john/key-auth where key-auth + does not follow plural form of http://<KONG_ADMIN>/key-auths. admin_api_nested_name + enables you to specify different name in those cases. +
    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.release | 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.release | 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.release | 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`. + +### Select 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 +``` + +### Iterate 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. + +### Insert 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`. + +### Update 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. + +### Upsert 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. + +### Delete 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 +``` + +## Cache 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.url}}). + +[Admin API]: /gateway/{{page.release}}/admin-api/ +[Plugin Development Kit]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.7.x/plugin-development/custom-logic.md b/app/gateway/2.7.x/plugin-development/custom-logic.md new file mode 100644 index 000000000000..bee285b7f834 --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/custom-logic.md @@ -0,0 +1,403 @@ +--- +title: Plugin Development - Implementing Custom Logic +book: plugin_dev +chapter: 3 +--- + +{:.note} +> **Note**: This chapter assumes that you are familiar with +[Lua](http://www.lua.org/). + +A {{site.base_gateway}} 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 {{site.base_gateway}}. To do so, the file +`kong.plugins..handler` must return a table with one or +more functions with predetermined names. Those functions will be +invoked by {{site.base_gateway}} at different phases when it processes traffic. + +The first parameter they take is always `self`. All functions except `init_worker` +can receive a second parameter which is a table with the plugin configuration. + +## Module + +``` +kong.plugins..handler +``` + +## Available contexts + +If you define any of the following functions in your `handler.lua` +file you'll implement custom logic at various entry-points +of {{site.base_gateway}}'s execution life-cycle: + +- **[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.
    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. +| `response` | [access] | Replaces both `header_filter()` and `body_filter()`. Executed after the whole response has been received from the upstream service, but before sending any part of it to the client. +| `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. This function 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. + +{:.note} +> **Note:** If a module implements the `response` function, {{site.base_gateway}} will automatically activate the "buffered proxy" mode, as if the [`kong.service.request.enable_buffering()` function][enable_buffering] had been called. Because of a current Nginx limitation, this doesn't work for HTTP/2 or gRPC upstreams. + +To reduce unexpected behaviour changes, {{site.base_gateway}} does not start if a plugin implements both `response` and either `header_filter` or `body_filter`. + +- **[Stream Module]** *is used for Plugins written for TCP and UDP 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. +| `certificate` | [ssl_certificate] | Executed during the SSL certificate serving phase of the SSL handshake. + +All of those functions, except `init_worker`, take one parameter which is given +by {{site.base_gateway}} 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.url}}). + +Note that UDP streams don't have real connections. {{site.base_gateway}} will consider all +packets with the same origin and destination host and port as a single +connection. After a configurable time without any packet, the connection is +considered closed and the `log` function is executed. + +[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 +[enable_buffering]: /gateway/{{page.release}}/pdk/kong.service.request/#kongservicerequestenable_buffering + + +## handler.lua specifications + +{{site.base_gateway}} processes requests in **phases**. A plugin is a piece of code that gets +activated by {{site.base_gateway}} as each phase is executed while the request gets proxied. + +Phases are limited in what they can do. For example, the `init_worker` phase +does not have access to the `config` parameter because that information isn't +available when kong is initializing each worker. + +A plugin's `handler.lua` must return a table containing the functions it must +execute on each phase. + +{{site.base_gateway}} can process HTTP and stream traffic. Some phases are executed +only when processing HTTP traffic, others when processing stream, +and some (like `init_worker` and `log`) are invoked by both kinds of traffic. + +In addition to functions, a plugin must define two fields: + +* `VERSION` is an informative field, not used by {{site.base_gateway}} directly. It usually + matches the version defined in a plugin's Rockspec version, when it exists. +* `PRIORITY` is used to sort plugins before executing each of their phases. + Plugins with a higher priority are executed first. See the + [plugin execution order](#plugins-execution-order) below + for more info about this field. + +The following example `handler.lua` file defines custom functions for all +the possible phases, in both http and stream traffic. It has no functionality +besides writing a message to the log every time a phase is invoked. Note +that a plugin doesn't need to provide functions for all phases. + +```lua +local CustomHandler = { + VERSION = "1.0.0", + PRIORITY = 10, +} + +function CustomHandler:init_worker() + -- Implement logic for the init_worker phase here (http/stream) + kong.log("init_worker") +end + + +function CustomHandler:preread(config) + -- Implement logic for the preread phase here (stream) + kong.log("preread") +end + + +function CustomHandler:certificate(config) + -- Implement logic for the certificate phase here (http/stream) + kong.log("certificate") +end + +function CustomHandler:rewrite(config) + -- Implement logic for the rewrite phase here (http) + kong.log("rewrite") +end + +function CustomHandler:access(config) + -- Implement logic for the rewrite phase here (http) + kong.log("access") +end + +function CustomHandler:header_filter(config) + -- Implement logic for the header_filter phase here (http) + kong.log("header_filter") +end + +function CustomHandler:body_filter(config) + -- Implement logic for the body_filter phase here (http) + kong.log("body_filter") +end + +function CustomHandler:log(config) + -- Implement logic for the log phase here (http/stream) + kong.log("log") +end + +-- return the created table, so that Kong can execute it +return CustomHandler +``` + +Note that in the example above we are using Lua's `:` shorthand syntax for +functions taking `self` as a first parameter. An equivalent unshortened version +of the `access` function would be: + +``` lua +function CustomHandler.access(self, config) + -- Implement logic for the rewrite phase here (http) + kong.log("access") +end +``` + +### Migrating from BasePlugin module + +The `BasePlugin` module is deprecated and will be removed in a future version +of {{site.base_gateway}}. If you have an old plugin that uses it, replace +the initial part: + +```lua +-- DEPRECATED -- +local BasePlugin = require "kong.plugins.base_plugin" +local CustomHandler = BasePlugin:extend() +CustomHandler.VERSION = "1.0.0" +CustomHandler.PRIORITY = 10 +``` + +with the current equivalent: +```lua +local CustomHandler = { + VERSION = "1.0.0", + PRIORITY = 10, +} +``` + +You don't need to add a `:new()` method or call any of the `CustomHandler.super.XXX:(self)` +methods. + +The plugin's logic doesn't need to be all defined inside the `handler.lua` file. +It can be split into several Lua files (also called *modules*). +The `handler.lua` module can use `require` to include other modules in your plugin. + +For example, the following plugin splits the functionality into three files. +`access.lua` and `body_filter.lua` return functions. They are in the same +folder as `handler.lua`, which requires and uses them to build the plugin: + +```lua +-- handler.lua +local access = require "kong.plugins.my-custom-plugin.access" +local body_filter = require "kong.plugins.my-custom-plugin.body_filter" + +local CustomHandler = { + VERSION = "1.0.0", + PRIORITY = 10 +} + +CustomHandler.access = access +CustomHandler.body_filter = body_filter + +return CustomHandler +``` + +```lua +-- access.lua +return function(self, config) + kong.log("access phase") +end +``` + +```lua +-- body_filter.lua +return function(self, config) + kong.log("body_filter phase") +end +``` + +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). {{site.base_gateway}} 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 {{site.base_gateway}}. + +When you are trying to implement some logic that needs to interact with {{site.base_gateway}} +(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, {{site.base_gateway}} 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.). + +{% navtabs %} +{% navtab Open-source or Free mode %} + +The following list includes all plugins bundled with open-source +{{site.base_gateway}} or {{site.base_gateway}} running in Free mode. + +{:.note} +> **Note:** The correlation-id plugin's execution order is different depending +on whether you're running {{site.base_gateway}} in Free mode or using the +open-source package. + +The current order of execution for the bundled plugins is: + +Plugin | Priority +----------------------------|---------- +pre-function | `+inf` +correlation-id | 100001 +zipkin | 100000 +bot-detection | 2500 +cors | 2000 +session | 1900 +jwt | 1005 +oauth2 | 1004 +key-auth | 1003 +ldap-auth | 1002 +basic-auth | 1001 +hmac-auth | 1000 +grpc-gateway | 998 +ip-restriction | 990 +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 +grpc-web | 3 +request-termination | 2 +correlation-id | 1 +post-function | -1000 + +{% endnavtab %} +{% navtab Enterprise %} +The following list includes all plugins bundled with a {{site.base_gateway}} +Enterprise subscription. + +The current order of execution for the bundled plugins is: + +Plugin | Priority +----------------------------|---------- +pre-function | `+inf` +correlation-id | 100001 +zipkin | 100000 +exit-transformer | 9999 +bot-detection | 2500 +cors | 2000 +route-by-header | 2000 +session | 1900 +oauth2-introspection | 1700 +acme | 1007 +mtls-auth | 1006 +jwt | 1005 +degraphql | 1005 +oauth2 | 1004 +vault-auth | 1003 +key-auth | 1003 +key-auth-enc | 1003 +ldap-auth | 1002 +ldap-auth-advanced | 1002 +basic-auth | 1001 +openid-connect | 1000 +hmac-auth | 1000 +request-validator | 999 +jwt-signer | 999 +grpc-gateway | 998 +application-registration | 995 +ip-restriction | 990 +request-size-limiting | 951 +acl | 950 +opa | 920 +rate-limiting-advanced | 902 +graphql-rate-limiting-advanced | 902 +rate-limiting | 901 +response-ratelimiting | 900 +jq | 811 +request-transformer-advanced | 802 +request-transformer | 801 +response-transformer-advanced | 800 +route-transformer-advanced | 800 +response-transformer | 800 +kafka-upstream | 751 +aws-lambda | 750 +azure-functions | 749 +graphql-proxy-cache-advanced | 100 +proxy-cache-advanced | 100 +proxy-cache | 100 +forward-proxy | 50 +prometheus | 13 +canary | 13 +http-log | 12 +statsd | 11 +statsd-advanced | 11 +datadog | 10 +file-log | 9 +udp-log | 8 +tcp-log | 7 +loggly | 6 +kafka-log | 5 +syslog | 4 +grpc-web | 3 +request-termination | 2 +mocking | -1 +post-function | -1000 + +{% endnavtab %} +{% endnavtabs %} +[lua-nginx-module]: https://github.com/openresty/lua-nginx-module +[pdk]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.7.x/plugin-development/distribution.md b/app/gateway/2.7.x/plugin-development/distribution.md new file mode 100644 index 000000000000..5fd373399915 --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/distribution.md @@ -0,0 +1,282 @@ +--- +title: Plugin Development - (un)Installing your plugin +book: plugin_dev +chapter: 10 +--- + +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 + + +## Install 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 of the following paths. + +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. + +### 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, for example +`http://myrepository.lan/rocks/my-plugin-0.1.0-1.all.rock`. + +### 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. + +### 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. + +For example, if the plugin `something` is located on the file system and the +handler file is in the following directory: + + /usr/local/custom/kong/plugins//handler.lua + +The location of the `kong` directory is `/usr/local/custom`, so the +proper path setup would be: + + lua_package_path = /usr/local/custom/?.lua;; + +#### Multiple plugins + +If you want 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". + +You can also set this property via its environment variable +equivalent: `KONG_LUA_PACKAGE_PATH`. + + +## Load the plugin + +1. 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 + + You can also set this property via its environment variable equivalent: + `KONG_PLUGINS`. + +1. Update the `plugins` directive for each node in your Kong cluster. + +1. Restart Kong to apply the plugin: + + kong restart + + Or, if you want to apply a plugin without stopping Kong, you can use this: + + kong prepare + kong reload + + +## 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. + +1. 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 + +2. Then, you should see the following log for each plugin being loaded: + + [debug] Loading plugin + + +## Remove 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. + + + +## Distribute 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][example-rockspec] using the `builtin` +build type to define modules in Lua notation and their corresponding file. + +For more information about the format, see the LuaRocks +[documentation on rockspecs][rockspec]. + + +## 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 Kong can't load +the `handler.lua` source file from the file system. To resolve, make sure that +the [`lua_package_path`](/gateway/{{page.release}}/reference/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 and 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. + +--- + +[rockspec]: https://github.com/keplerproject/luarocks/wiki/Creating-a-rock +[plugin-template]: https://github.com/Kong/kong-plugin +[example-rockspec]: https://github.com/Kong/kong-plugin/blob/master/kong-plugin-myplugin-0.1.0-1.rockspec diff --git a/app/gateway/2.7.x/plugin-development/entities-cache.md b/app/gateway/2.7.x/plugin-development/entities-cache.md new file mode 100644 index 000000000000..667cd65db5f8 --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/entities-cache.md @@ -0,0 +1,344 @@ +--- +title: Plugin Development - Caching Custom Entities +book: plugin_dev +chapter: 7 +--- + +Your plugin may need to frequently access custom entities (explained in the +[previous chapter]({{page.book.previous.url}})) 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 +``` + +## Cache custom entities + +Once you have defined your custom entities, you can cache them in-memory in +your code by using the [kong.cache](/gateway/{{page.release}}/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. + +### Update or delete 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 want your cached entities to 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, + admin_api_name = "key-auths", + admin_api_nested_name = "key-auth", + 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](/gateway/{{page.release}}/reference/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. +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.url}}). + +[Admin API]: /gateway/{{page.release}}/admin-api/ +[Plugin Development Kit]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.7.x/plugin-development/file-structure.md b/app/gateway/2.7.x/plugin-development/file-structure.md new file mode 100644 index 000000000000..be9b4eb969b1 --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/file-structure.md @@ -0,0 +1,115 @@ +--- +title: Plugin Development - File Structure +book: plugin_dev +chapter: 2 +--- + +{:.note} +> **Note**: This chapter assumes that you are familiar with +[Lua](http://www.lua.org/). + +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 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`](/gateway/{{page.release}}/reference/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](/gateway/{{page.release}}/reference/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. + +[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/gateway/2.7.x/plugin-development/index.md b/app/gateway/2.7.x/plugin-development/index.md new file mode 100644 index 000000000000..9a14c070de69 --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/index.md @@ -0,0 +1,31 @@ +--- +title: Plugin Development - Introduction +book: plugin_dev +chapter: 1 +--- + +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** (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. + +[lua-nginx-module]: https://github.com/openresty/lua-nginx-module +[Plugin Development Kit]: /gateway/{{page.release}}/pdk diff --git a/app/gateway/2.7.x/plugin-development/plugin-configuration.md b/app/gateway/2.7.x/plugin-development/plugin-configuration.md new file mode 100644 index 000000000000..01bbf41e4562 --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/plugin-configuration.md @@ -0,0 +1,402 @@ +--- +title: Plugin Development - Plugin Configuration +book: plugin_dev +chapter: 4 +--- + +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, or Consumer. + +For example, a user performs the following request: + +```bash +$ curl -X POST http://localhost: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. +| `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 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 + }, + { + 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](/gateway/{{page.release}}/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://localhost: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]. + +[Admin API]: /gateway/{{page.release}}/admin-api +[Plugin Development Kit]: /gateway/{{page.release}}/pdk +[the Key-Auth plugin source code]: https://github.com/Kong/kong/blob/master/kong/plugins/key-auth/schema.lua diff --git a/app/gateway/2.7.x/plugin-development/tests.md b/app/gateway/2.7.x/plugin-development/tests.md new file mode 100644 index 000000000000..46d4841937b9 --- /dev/null +++ b/app/gateway/2.7.x/plugin-development/tests.md @@ -0,0 +1,102 @@ +--- +title: Plugin Development - Writing tests +book: plugin_dev +chapter: 9 +--- + +If you are serious about your plugin, 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](https://github.com/lunarmodules/busted/) running with the +[resty-cli](https://github.com/openresty/resty-cli) interpreter, though you are +free to use a different one. 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.konghq.com" + } + + 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 +``` + +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. + +For a real-world example, see the +[Key-Auth plugin specs](https://github.com/Kong/kong/tree/master/spec/03-plugins/09-key-auth). + diff --git a/app/gateway/2.7.x/reference/cli.md b/app/gateway/2.7.x/reference/cli.md new file mode 100644 index 000000000000..8de3d34434a2 --- /dev/null +++ b/app/gateway/2.7.x/reference/cli.md @@ -0,0 +1,358 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# the files in https://github.com/Kong/kong/tree/master/autodoc/cli +# +title: CLI Reference +source_url: https://github.com/Kong/kong/tree/master/autodoc/cli +--- + +## 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) + +## Available commands + + +### kong check + +``` +Usage: kong check + +Check the validity of a given Kong configuration file. + + (default /etc/kong/kong.conf) configuration file + +``` + +--- + + +### 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. If a filename + is not given, ./kong.yml is used + by default. + + db_import Import a declarative config file into + the Kong database. + + db_export [] Export the Kong database into a + declarative config file. If a filename + is not given, ./kong.yml is used + by default. + + 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. + +``` + +{:.note} +> **Note:** `db_export` is only supported with open-source +{{site.base_gateway}} packages. + +--- + + +### 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 + +``` + +--- + + +### kong hybrid + +``` +Usage: kong hybrid COMMAND [OPTIONS] + +Hybrid mode utilities for Kong. + +The available commands are: + gen_cert [ ] Generate a certificate/key pair that is suitable + for use in hybrid mode deployment. + Cert and key will be written to + './cluster.crt' and './cluster.key' inside + the current directory unless filenames are given. + +Options: + -d,--days (optional number) Override certificate validity duration. + Default: 1095 days (3 years) + +``` + +--- + + +### 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. + The `reset` command erases all of the data + in Kong's database and deletes all of the schemas. + + migrate-community-to-enterprise Migrates Kong Community entities to + Kong Enterprise in the default + workspace. + + upgrade-workspace-table Outputs a script to be run on the db to + upgrade the entity for 2.x workspaces + implementation. + + reinitialize-workspace-entity-counters Resets the entity counters from the + database entities. +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. + + With 'migrate-community-to-enterprise' it + disables the workspace entities check. + + --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. + + -p,--prefix (optional string) Override prefix directory. + + --v verbose + --vv debug + +``` + +--- + + +### 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 + +``` + +--- + + +### 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 + +``` + +--- + + +### 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 + +``` + +--- + + +### 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) + +``` + +--- + +### kong runner +{:.badge .enterprise} + +``` +Usage: kong runner [file] [args] +Execute a lua file in a kong node. the `kong` variable is available to +reach the DAO, PDK, etc. The variable `args` can be used to access all +arguments (args[1] being the lua filename being run). +Example usage: + kong runner file.lua arg1 arg2 + echo 'print("foo")' | kong runner +``` + +--- + + +### 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. + +``` + +--- + + +### 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 + +``` + +--- + + +### 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 + +``` + +--- + + +[configuration-reference]: /gateway/{{page.release}}/reference/configuration/ diff --git a/app/gateway/2.7.x/reference/clustering.md b/app/gateway/2.7.x/reference/clustering.md new file mode 100644 index 000000000000..b27bcf71c7d7 --- /dev/null +++ b/app/gateway/2.7.x/reference/clustering.md @@ -0,0 +1,302 @@ +--- +title: Clustering Reference +--- + +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, and so on. 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. + +## Single node Kong clusters + + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + + +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 +``` + +## 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**. + +### Use read-only replicas when deploying Kong clusters with PostgreSQL + +When using PostgreSQL as the backend storage, you can optionally enable +Kong to serve read queries from a separate database instance. + +One of the common use cases of this feature is to deploy Kong with the +Amazon Aurora service as backend storage. Because Aurora natively supports +read-only instances, enabling the read-only connection support in Kong +greatly reduces the load on the main database instance since read-only +queries are no longer sent to it. + +To learn more about how to configure this feature, refer to the +[Datastore section](/gateway/{{page.release}}/reference/configuration/#datastore-section) +of the Configuration reference. + +## 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. + +## How to configure database caching? + +You can configure three properties in the Kong configuration file, the most +important one being `db_update_frequency`, which determine where your Kong +nodes stand on the performance versus consistency trade-off. + +Kong comes with default values tuned for consistency so that you can +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 means that the polling +job will execute more frequently, but that your Kong nodes will keep up +with changes you apply. A higher value means 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. + + +### 2. [db_update_propagation][db_update_propagation] (default: 0s) + + +If your database itself is eventually consistent (that is, 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 eventually 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. + + +### 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/PostgreSQL). 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. + +### 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 in 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. + +Setting the `cassandra_refresh_frequency` option to `0` is not advised, as a Kong +restart will be required to discover any changes to the Cassandra cluster topology. + +## Interacting with the cache via the Admin API + +If for some reason, you want 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. + +### 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. + +### Purge a node's cache + +**Endpoint** + +
    /cache
    + +**Response** + +``` +HTTP 204 No Content +``` + +**Note**: Be wary of using this endpoint on a node running in production with warm cache. +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). + + +[db_update_frequency]: /gateway/{{page.release}}/reference/configuration/#db_update_frequency +[db_update_propagation]: /gateway/{{page.release}}/reference/configuration/#db_update_propagation +[db_cache_ttl]: /gateway/{{page.release}}/reference/configuration/#db_cache_ttl diff --git a/app/gateway/2.7.x/reference/configuration.md b/app/gateway/2.7.x/reference/configuration.md new file mode 100644 index 000000000000..8a1bd799903c --- /dev/null +++ b/app/gateway/2.7.x/reference/configuration.md @@ -0,0 +1,3760 @@ +--- +# +# WARNING: this file was auto-generated by a script. +# DO NOT edit this file directly. Instead, send a pull request to change +# the files in https://github.com/Kong/docs.konghq.com/tree/main/autodoc-conf-ee +# +title: Configuration Reference for Kong Gateway +source_url: https://github.com/Kong/kong-ee/edit/master/kong.conf.default +--- + +## 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 {PATH/TO/kong.conf} + +configuration at {PATH/TO/kong.conf} 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 {kong.conf} --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 the following +supported namespaces will be converted into an equivalent Nginx +directive by removing the prefix and added to the appropriate section of the +Nginx configuration: + +- `nginx_main_`: Injects `` in Kong's configuration + `main` context. +- `nginx_events_`: Injects `` in Kong's `events {}` + block. +- `nginx_http_`: Injects `` in Kong's `http {}` block. +- `nginx_proxy_`: Injects `` in Kong's proxy + `server {}` block. +- `nginx_upstream_`: Injects `` in Kong's proxy + `upstream {}` block. +- `nginx_admin_`: Injects `` in Kong's Admin API + `server {}` block. +- `nginx_status_`: Injects `` in Kong's Status API + `server {}` block (only effective if `status_listen` is enabled). +- `nginx_stream_`: Injects `` in Kong's stream module + `stream {}` block (only effective if `stream_listen` is enabled). +- `nginx_sproxy_`: Injects `` in Kong's stream module + `server {}` block (only effective if `stream_listen` is enabled). +- `nginx_supstream_`: Injects `` in Kong's stream + module `upstream {}` block. + +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; +``` + +If you want to add the same directive multiple times, you can specify it like the following example: + +```bash +export "KONG_NGINX_MAIN_ENV=HTTP_SSO_ENDPOINT;env PROXY_SSO_ENDPOINT" +export HTTP_SSO_ENDPOINT=http://example.com +export PROXY_SSO_ENDPOINT=http://example.com +``` + +This results in Kong injecting this line: + +``` +env HTTP_SSO_ENDPOINT;env PROXY_SSO_ENDPOINT; +``` + +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 [Nginx reference](https://nginx.org/en/docs/beginners_guide.html#conf_structure). + +For a list of Nginx directives, see the [Nginx directives index](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 following Lua functions are available in the [templating engine][pl.template]: + +- `pairs`, `ipairs` +- `tostring` +- `os.getenv` + +The default template for +Kong Gateway can be found by entering the following command on the system +running your Kong instance: `find / -type d -name "templates" | grep kong`. For +open-source Kong Gateway, you can also see the +[templates directory][templates]. + +The template is split in two +Nginx configuration files: `nginx.lua` and `nginx_kong.lua`. The former is +minimal 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 +``` + + +## 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` property. + +**Default:** `logs/error.log` + +--- + +#### proxy_stream_access_log + +Path for tcp streams proxy port 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. + +`basic` is defined as `'$remote_addr [$time_local] ' '$protocol $status +$bytes_sent $bytes_received ' '$session_time'` + +**Default:** `logs/access.log basic` + +--- + +#### proxy_stream_error_log + +Path for tcp streams proxy port request error logs. The granularity of these +logs is adjusted by the `log_level` property. + +**Default:** `logs/error.log` + +--- + +#### admin_access_log + +Path for Admin API request access logs. If Hybrid Mode is enabled and the +current node is set to be the Control Plane, then the connection requests from +Data Planes are also written to this file with server name +"kong_cluster_listener". + +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` property. + +**Default:** `logs/error.log` + +--- + +#### status_access_log + +Path for Status API request access logs. The default value of `off` implies +that logging for this API is disabled by default. + +If this value is a relative path, it will be placed under the `prefix` +location. + +**Default:** `off` + +--- + +#### status_error_log + +Path for Status API request error logs. The granularity of these logs is +adjusted by the `log_level` property. + +**Default:** `logs/status_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` + +--- + +#### pluginserver_names + +Comma-separated list of names for pluginserver processes. The actual names are +used for log messages and to relate the actual settings. + +**Default:** none + +--- + +#### pluginserver_XXX_socket + +Path to the unix socket used by the pluginserver. + +**Default:** `/.socket` + +--- + +#### pluginserver_XXX_start_cmd + +Full command (including any needed arguments) to start the pluginserver + +**Default:** `/usr/local/bin/` + +--- + +#### pluginserver_XXX_query_cmd + +Full command to "query" the pluginserver. Should produce a JSON with the +dump info of all plugins it manages + +**Default:** `/usr/local/bin/query_` + +--- + +#### port_maps + +With this configuration parameter, you can let the Kong to know about the port +from which the packets are forwarded to it. This is fairly common when running +Kong in a containerized or virtualized environment. + +For example, `port_maps=80:8000, 443:8443` instructs Kong that the port 80 is +mapped to 8000 (and the port 443 to 8443), where 8000 and 8443 are the ports +that Kong is listening to. + +This parameter helps Kong set a proper forwarded upstream HTTP request header +or to get the proper forwarded port with the Kong PDK (in case other means +determining it has failed). It changes routing by a destination port to route by +a port from which packets are forwarded to Kong, and similarly it changes the +default plugin log serializer to use the port according to this mapping instead +of reporting the port Kong is listening to. + +**Default:** none + +--- + +#### anonymous_reports + +Send anonymous usage data such as error stack traces to help improve Kong. + +**Default:** `on` + +--- + + +### Hybrid Mode section + +#### role + +Use this setting to enable Hybrid Mode, This allows running some Kong nodes in +a control plane role with a database and have them deliver configuration updates +to other nodes running to DB-less running in a Data Plane role. + +Valid values to this setting are: + +- `traditional`: do not use Hybrid Mode. +- `control_plane`: this node runs in a control plane role. It can use a + database and will deliver configuration updates to data plane nodes. +- `data_plane`: this is a data plane node. It runs DB-less and receives + configuration updates from a control plane node. + +**Default:** `traditional` + +--- + +#### cluster_mtls + +Sets the verification between nodes of the cluster. + +Valid values to this setting are: + +- `shared`: use a shared certificate/key pair specified with the `cluster_cert` + and `cluster_cert_key` settings. Note that CP and DP nodes have to present the + same certificate to establish mTLS connections. +- `pki`: use `cluster_ca_cert`, `cluster_server_name` and `cluster_cert` for + verification. These are different certificates for each DP node, but issued by + a cluster-wide common CA certificate: `cluster_ca_cert`. +- `pki_check_cn` : similar to `pki`, but additionally + checks for the Common Name of the data plane certificate specified in + `cluster_allowed_common_names`. + +**Default:** `shared` + +--- + +#### cluster_cert + +Filename of the cluster certificate to use when establishing secure +communication between control and data plane nodes. + +You can use the `kong hybrid` command to generate the certificate/key pair. + +Under `shared` mode, it must be the same for all nodes. Under `pki` mode it +should be a different certificate for each DP node. + +**Default:** none + +--- + +#### cluster_cert_key + +Filename of the cluster certificate key to use when establishing secure +communication between control and data plane nodes. + +You can use the `kong hybrid` command to generate the certificate/key pair. + +Under `shared` mode, it must be the same for all nodes. Under `pki` mode it +should be a different certificate for each DP node. + +**Default:** none + +--- + +#### cluster_ca_cert + +The trusted CA certificate file in PEM format used for Control Plane to verify +Data Plane's certificate and Data Plane to verify Control Plane's certificate. + +Required on data plane if `cluster_mtls` is set to `pki`. + +If Control Plane certificate is issued by a well known CA, user can set +`lua_ssl_trusted_certificate=system` on Data Plane and leave this field empty. + +This field is ignored if `cluster_mtls` is set to `shared`. + +**Default:** none + +--- + +#### cluster_allowed_common_names + +The list of Common Names that are allowed to connect to the control plane. +Multiple entries may be supplied in a comma-separated string. When not +set, only Data Planes with the same parent domain as the +Control Plane cert are allowed to connect. + +This field is ignored if `cluster_mtls` is not set to `pki_check_cn`. + +**Default:** none + +--- + +### Hybrid Mode Data Plane section + +#### cluster_server_name + +The server name used in the SNI of the TLS connection from a DP node to a CP +node. + +Must match the Common Name (CN) or Subject Alternative Name (SAN) found in the +CP certificate. + +If `cluster_mtls` is set to `shared`, this setting is ignored and +`kong_clustering` is used. + +**Default:** none + +--- + +#### cluster_control_plane + +To be used by data plane nodes only: address of the control plane node from +which configuration updates will be fetched, in `host:port` format. + +**Default:** none + +--- + +#### cluster_telemetry_endpoint +{:.badge .enterprise} + +To be used by data plane nodes only: telemetry address of the control plane +node to which telemetry updates will be posted in `host:port` format. + +**Default:** none + +--- + +#### cluster_telemetry_server_name +{:.badge .enterprise} + +The SNI (Server Name Indication extension) to use for Vitals telemetry data. + +**Default:** none + +--- + +#### data_plane_config_cache_mode +{:.badge .enterprise} + +Data planes can store their config to file system as a backup in case the node +is restarted or reloaded to faster bring the node in configured state or in case +there are issues connecting to control plane. + +This parameter can be used to control the behavior. + +To be used by data plane nodes only: `unencrypted` = stores config cache +unencrypted `encrypted` = stores config cache encrypted `off` = does not store +the config cache + +**Default:** `unencrypted` + +--- + +#### data_plane_config_cache_path +{:.badge .enterprise} + +The unencrypted config cache is stored by default to Kong `prefix` with a +filename `config.cache.json.gz`. + +The encrypted config cache is stored by default to Kong `prefix` with a +filename `.config.cache.jwt` Alternatively you can specify path for config cache +with this parameter, e.g. `/tmp/kong-config-cache`. + +**Default:** none + +--- + + +### Hybrid Mode Control Plane section + +#### cluster_listen + +Comma-separated list of addresses and ports on which the cluster control plane +server should listen for data plane connections. + +The cluster communication port of the control plane must be accessible by all +the data planes within the same cluster. This port is mTLS protected to ensure +end-to-end security and integrity. + +This setting has no effect if `role` is not set to `control_plane`. + +Connection made to this endpoint are logged to the same location as Admin API +access logs. + +See `admin_access_log` config description for more information. + +**Default:** `0.0.0.0:8005` + +--- + +#### cluster_telemetry_listen +{:.badge .enterprise} + +Comma-separated list of addresses and ports on which the cluster control plane +server should listen for data plane telemetry connections. + +The cluster communication port of the control plane must be accessible by all +the data planes within the same cluster. + +This setting has no effect if `role` is not set to `control_plane`. + +**Default:** `0.0.0.0:8006` + +--- + +#### cluster_data_plane_purge_delay + +How many seconds must pass from the time a DP node becomes offline to the time +its entry gets removed from the database, as returned by the +/clustering/data-planes Admin API endpoint. + +This is to prevent the cluster data plane table from growing indefinitely. The +default is set to 14 days. That is, if CP haven't heard from a DP for 14 days, +its entry will be removed. + +**Default:** `1209600` + +--- + +#### cluster_ocsp + +Whether to check for revocation status of DP certificates using OCSP (Online +Certificate Status Protocol). + +If enabled, the DP certificate should contain the "Certificate Authority +Information Access" extension and the OCSP method with URI of which the OCSP +responder can be reached from CP. + +OCSP checks are only performed on CP nodes, it has no effect on DP nodes. + +Valid values to this setting are: + +- `on`: OCSP revocation check is enabled and DP must pass the check in order to + establish connection with CP. +- `off`: OCSP revocation check is disabled. +- `optional`: OCSP revocation check will be attempted, however, if the required + extension is not found inside DP provided certificate or communication with + the OCSP responder failed, then DP is still allowed through. + +**Default:** `off` + +--- + +#### cluster_max_payload + +This sets the maximum payload size allowed to be sent across from CP to DP in +Hybrid mode. + +Default is 4Mb - 4 * 1024 * 1024 due to historical reasons. + +**Default:** `4194304` + +--- + +### 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. +- `deferred` instructs to use a deferred accept on Linux (the TCP_DEFER_ACCEPT + socket option). +- `bind` instructs to make a separate bind() call for a given address:port + pair. +- `reuseport` instructs to create an individual listening socket for each + worker process allowing the Kernel to better distribute incoming connections + between worker processes +- `backlog=N` sets the maximum length for the queue of pending TCP connections. + This number should not be too small in order to prevent clients seeing + "Connection refused" error connecting to a busy Kong instance. **Note:** on + Linux, this value is limited by the setting of `net.core.somaxconn` Kernel + parameter. In order for the larger `backlog` set here to take effect it is + necessary to raise `net.core.somaxconn` at the same time to match or exceed + the `backlog` number set. + +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 reuseport backlog=16384, 0.0.0.0:8443 http2 ssl reuseport backlog=16384` + +--- + +#### proxy_url + +Kong Proxy URL + +The lookup, or balancer, address for your Kong Proxy nodes. + +This value is commonly used in a microservices or service-mesh oriented +architecture. + +Accepted format (parts in parentheses are optional): + +`://(:(/))` + +Examples: + +- `://:` -> `proxy_url = http://127.0.0.1:8000` +- `SSL ://` -> `proxy_url = https://proxy.domain.tld` +- `:///` -> `proxy_url = http://dev-machine/dev-285` + +By default, Kong Manager, and Kong Portal will use the window request host and +append the resolved listener port depending on the requested protocol. + +**Default:** none + +--- + +#### 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: + +- `ssl` will require that all connections made through a particular + address/port be made with TLS enabled. +- `proxy_protocol` will enable usage of the PROXY protocol for a given + address/port. +- `bind` instructs to make a separate bind() call for a given address:port + pair. +- `reuseport` instructs to create an individual listening socket for each + worker process allowing the Kernel to better distribute incoming connections + between worker processes +- `backlog=N` sets the maximum length for the queue of pending TCP connections. + This number should not be too small in order to prevent clients seeing + "Connection refused" error connecting to a busy Kong instance. **Note:** on + Linux, this value is limited by the setting of `net.core.somaxconn` Kernel + parameter. In order for the larger `backlog` set here to take effect it is + necessary to raise `net.core.somaxconn` at the same time to match or exceed + the `backlog` number set. + +Examples: + +``` +stream_listen = 127.0.0.1:7000 reuseport backlog=16384 +stream_listen = 0.0.0.0:989 reuseport backlog=65536, 0.0.0.0:20 +stream_listen = [::1]:1234 backlog=16384 +``` + +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_api_uri + +Hierarchical part of a URI which is composed optionally of a host, port, and +path at which the Admin API accepts HTTP or HTTPS traffic. When this config is +disabled, Kong Manager will use the window protocol + host and append the +resolved admin_listen HTTP/HTTPS port. + +**Default:** none + +--- + +#### 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. +- `proxy_protocol` will enable usage of the PROXY protocol for a given + address/port. +- `deferred` instructs to use a deferred accept on Linux (the TCP_DEFER_ACCEPT + socket option). +- `bind` instructs to make a separate bind() call for a given address:port + pair. +- `reuseport` instructs to create an individual listening socket for each + worker process allowing the Kernel to better distribute incoming connections + between worker processes +- `backlog=N` sets the maximum length for the queue of pending TCP connections. + This number should not be too small in order to prevent clients seeing + "Connection refused" error connecting to a busy Kong instance. **Note:** on + Linux, this value is limited by the setting of `net.core.somaxconn` Kernel + parameter. In order for the larger `backlog` set here to take effect it is + necessary to raise `net.core.somaxconn` at the same time to match or exceed + the `backlog` number set. + +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: `admin_listen = 127.0.0.1:8444 http2 ssl` + +**Default:** `127.0.0.1:8001 reuseport backlog=16384, 127.0.0.1:8444 http2 ssl reuseport backlog=16384` + +--- + +#### status_listen + +Comma-separated list of addresses and ports on which the Status API should +listen. + +The Status API is a read-only endpoint allowing monitoring tools to retrieve +metrics, healthiness, and other non-sensitive information of the current Kong +node. + +The following suffix can be specified for each pair: + +- `ssl` will require that all connections made through a particular + address/port be made with TLS enabled. + +This value can be set to `off`, disabling the Status API for this node. + +Example: `status_listen = 0.0.0.0:8100` + +**Default:** `off` + +--- + +#### 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` + +**Note**: If the `kong` user and the `kong` group are not available, the +default user and group credentials will be `nobody nobody`. + +**Default:** `kong kong` + +--- + +#### 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 the equivalent Nginx 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 each of the two in-memory caches for database entities. The accepted +units are `k` and `m`, with a minimum recommended value of a few MBs. + +**Note**: As this option controls the size of two different cache entries, the +total memory Kong uses to cache entities might be double this value. + +**Default:** `128m` + +--- + +#### ssl_cipher_suite + +Defines the TLS ciphers served by Nginx. + +Accepted values are `modern`, `intermediate`, `old`, `fips` or `custom`. + +See https://wiki.mozilla.org/Security/Server_Side_TLS for detailed descriptions +of each cipher suite. `fips` cipher suites are as decribed in +https://wiki.openssl.org/index.php/FIPS_mode_and_TLS. + +**Default:** `intermediate` + +--- + +#### 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_protocols + +Enables the specified protocols for client-side connections. The set of +supported protocol versions also depends on the version of OpenSSL Kong was +built with. This value is ignored if `ssl_cipher_suite` is not `custom`. + +See http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols + +**Default:** `TLSv1.1 TLSv1.2 TLSv1.3` + +--- + +#### ssl_prefer_server_ciphers + +Specifies that server ciphers should be preferred over client ciphers when +using the SSLv3 and TLS protocols. This value is ignored if `ssl_cipher_suite` +is not `custom`. + +See +http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_prefer_server_ciphers + +**Default:** `on` + +--- + +#### ssl_dhparam + +Defines DH parameters for DHE ciphers from the predefined groups: `ffdhe2048`, +`ffdhe3072`, `ffdhe4096`, `ffdhe6144`, `ffdhe8192`, or from the absolute path to +a parameters file. + +This value is ignored if `ssl_cipher_suite` is `modern` or `intermediate`. The +reason is that `modern` has no ciphers that needs this, and `intermediate` uses +`ffdhe2048`. + +See http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam + +**Default:** none + +--- + +#### ssl_session_tickets + +Enables or disables session resumption through TLS session tickets. This has no +impact when used with TLSv1.3. + +Kong enables this by default for performance reasons, but it has security +implications: https://github.com/mozilla/server-side-tls/issues/135 + +See http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets + +**Default:** `on` + +--- + +#### ssl_session_timeout + +Specifies a time during which a client may reuse the session parameters. See +the rationale: https://github.com/mozilla/server-side-tls/issues/198 + +See http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_timeout + +**Default:** `1d` + +--- + +#### ssl_cert + +Comma-separated list of the absolute path to the certificates for +`proxy_listen` values with TLS enabled. + +If more than one certificates are specified, it can be used to provide +alternate type of certificate (for example, ECC certificate) that will be served +to clients that supports them. Note to properly serve using ECC certificates, it +is recommended to also set `ssl_cipher_suite` to `modern` or `intermediate`. + +Unless this option is explicitly set, Kong will auto-generate a pair of default +certificates (RSA + ECC) first time it starts up and use it for serving TLS +requests. + +**Default:** none + +--- + +#### ssl_cert_key + +Comma-separated list of the absolute path to the keys for `proxy_listen` values +with TLS enabled. + +If more than one certificate was specified for `ssl_cert`, then this option +should contain the corresponding key for all certificates provided in the same +order. + +Unless this option is explicitly set, Kong will auto-generate a pair of default +private keys (RSA + ECC) first time it starts up and use it for serving TLS +requests. + +**Default:** none + +--- + +#### client_ssl + +Determines if Nginx should attempt to send client-side TLS certificates and +perform Mutual TLS Authentication with upstream service when proxying requests. + +**Default:** `off` + +--- + +#### client_ssl_cert + +If `client_ssl` is enabled, the absolute path to the client certificate for the +`proxy_ssl_certificate` directive. + +This value can be overwritten dynamically with the `client_certificate` +attribute of the `Service` object. + +**Default:** none + +--- + +#### client_ssl_cert_key + +If `client_ssl` is enabled, the absolute path to the client TLS key for the +`proxy_ssl_certificate_key` directive. + +This value can be overwritten dynamically with the `client_certificate` +attribute of the `Service` object. + +**Default:** none + +--- + +#### admin_ssl_cert + +Comma-separated list of the absolute path to the certificates for +`admin_listen` values with TLS enabled. + +See docs for `ssl_cert` for detailed usage. + +**Default:** none + +--- + +#### admin_ssl_cert_key + +Comma-separated list of the absolute path to the keys for `admin_listen` values +with TLS enabled. + +See docs for `ssl_cert_key` for detailed usage. + +**Default:** none + +--- + +#### status_ssl_cert + +Comma-separated list of the absolute path to the certificates for +`status_listen` values with TLS enabled. + +See docs for `ssl_cert` for detailed usage. + +**Default:** none + +--- + +#### status_ssl_cert_key + +Comma-separated list of the absolute path to the keys for `status_listen` +values with TLS enabled. + +See docs for `ssl_cert_key` for detailed usage. + +**Default:** none + +--- + +#### 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). +- `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-Response-Latency`: time taken (in millisecond) by Kong to produce a + response in case of e.g. plugin short-circuiting the request, or in in case of + an error. +- `X-Kong-Upstream-Latency`: Time taken (in milliseconds) by the upstream + service to send response headers. +- `X-Kong-Admin-Latency`: Time taken (in milliseconds) by Kong to process an + Admin API request. +- `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 `X-Kong-Proxy-Latency`, + `X-Kong-Response-Latency`, `X-Kong-Admin-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` + +--- + +#### 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` + +--- + +#### upstream_keepalive_pool_size + +Sets the default size of the upstream keepalive connection pools. + +Upstream keepalive connection pools are segmented by the `dst ip/dst port/SNI` +attributes of a connection. + +A value of `0` will disable upstream keepalive connections by default, forcing +each upstream request to open a new connection. + +**Default:** `60` + +--- + +#### upstream_keepalive_max_requests + +Sets the default maximum number of requests than can be proxied upstream +through one keepalive connection. + +After the maximum number of requests is reached, the connection will be closed. + +A value of `0` will disable this behavior, and a keepalive connection can be +used to proxy an indefinite number of requests. + +**Default:** `100` + +--- + +#### upstream_keepalive_idle_timeout + +Sets the default timeout (in seconds) for which an upstream keepalive +connection should be kept open. When the timeout is reached while the connection +has not been reused, it will be closed. + +A value of `0` will disable this behavior, and an idle keepalive connection may +be kept open indefinitely. + +**Default:** `60` + +--- + + +### NGINX Injected Directives section + +Nginx directives can be dynamically injected in the runtime nginx.conf file +without requiring a custom Nginx configuration template. + +All configuration properties respecting the naming scheme +`nginx__` will result in `` being injected in +the Nginx configuration block corresponding to the property's ``. + +Example: `nginx_proxy_large_client_header_buffers = 8 24k` + +Will inject the following directive in Kong's proxy `server {}` block: + +`large_client_header_buffers 8 24k;` + +The following namespaces are supported: + +- `nginx_main_`: Injects `` in Kong's configuration + `main` context. +- `nginx_events_`: Injects `` in Kong's `events {}` + block. +- `nginx_http_`: Injects `` in Kong's `http {}` block. +- `nginx_proxy_`: Injects `` in Kong's proxy `server {}` + block. +- `nginx_upstream_`: Injects `` in Kong's proxy `upstream + {}` block. +- `nginx_admin_`: Injects `` in Kong's Admin API `server + {}` block. +- `nginx_status_`: Injects `` in Kong's Status API + `server {}` block (only effective if `status_listen` is enabled). +- `nginx_stream_`: Injects `` in Kong's stream module + `stream {}` block (only effective if `stream_listen` is enabled). +- `nginx_sproxy_`: Injects `` in Kong's stream module + `server {}` block (only effective if `stream_listen` is enabled). +- `nginx_supstream_`: Injects `` in Kong's stream module + `upstream {}` block. + +As with other configuration properties, Nginx directives can be injected via +environment variables when capitalized and prefixed with `KONG_`. + +Example: `KONG_NGINX_HTTP_SSL_PROTOCOLS` -> `nginx_http_ssl_protocols` + +Will inject the following directive in Kong's `http {}` block: + +`ssl_protocols ;` + +If different sets of protocols are desired between the proxy and Admin API +server, you may specify `nginx_proxy_ssl_protocols` and/or +`nginx_admin_ssl_protocols`, both of which taking precedence over the `http {}` +block. + +--- + +#### nginx_main_worker_rlimit_nofile + +Changes the limit on the maximum number of open files for worker processes. + +The special and default value of `auto` sets this value to `ulimit -n` with the +upper bound limited to 16384 as a measure to protect against excess memory use. + +See http://nginx.org/en/docs/ngx_core_module.html#worker_rlimit_nofile + +**Default:** `auto` + +--- + +#### nginx_events_worker_connections + +Sets the maximum number of simultaneous connections that can be opened by a +worker process. + +The special and default value of `auto` sets this value to `ulimit -n` with the +upper bound limited to 16384 as a measure to protect against excess memory use. + +See http://nginx.org/en/docs/ngx_core_module.html#worker_connections + +**Default:** `auto` + +--- + +#### nginx_http_client_header_buffer_size + +Sets buffer size for reading the client request headers. + +See +http://nginx.org/en/docs/http/ngx_http_core_module.html#client_header_buffer_size + +**Default:** `1k` + +--- + +#### nginx_http_large_client_header_buffers + +Sets the maximum number and size of buffers used for reading large clients +requests headers. + +See +http://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers + +**Default:** `4 8k` + +--- + +#### nginx_http_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 + +**Default:** `0` + +--- + +#### nginx_admin_client_max_body_size + +Defines the maximum request body size for Admin API. + +**Default:** `10m` + +--- + +#### nginx_http_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 + +**Default:** `8k` + +--- + +#### nginx_admin_client_body_buffer_size + +Defines the buffer size for reading the request body on Admin API. + +**Default:** `10m` + +--- + +#### nginx_http_lua_regex_match_limit + +Global `MATCH_LIMIT` for PCRE regex matching. The default of `100000` should +ensure at worst any regex Kong executes could finish within roughly 2 seconds. + +**Default:** `100000` + +--- + + +### Datastore section + + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + + +Kong can run with a database to store coordinated data between Kong nodes in a +cluster, or without a database, where each node stores its information +independently in memory. + +When using a database, Kong will store data for all its entities (such as +Routes, Services, Consumers, and Plugins) in a database, and +all Kong nodes belonging to the same cluster must connect themselves to the same +database. + +When not using a database, Kong is said to be in "DB-less mode": it will keep +its entities in memory, and each node needs to have this data entered via a +declarative configuration file, which can be specified through the +`declarative_config` property, or via the Admin API using the `/config` +endpoint. + +When using PostgreSQL as the backend storage, you can optionally enable Kong to +serve read queries from a separate database instance. + +When the number of proxies is large, this can greatly reduce the load on the +main PostgreSQL instance and achieve better scalability. It may also reduce the +latency jitter if the Kong proxy node's latency to the main PostgreSQL instance is +high. + +The read-only PostgreSQL instance only serves read queries and write queries +still goes to the main connection. The read-only PostgreSQL instance can be +eventually consistent while replicating changes from the main instance. + +At least the `pg_ro_host` config is needed to enable this feature. + +By default, all other database config for the read-only connection are +inherited from the corresponding main connection config described above but may +be optionally overwritten explicitly using the `pg_ro_*` config below. + +--- + +#### database + +Determines which of PostgreSQL or Cassandra this node will use as its +datastore. + +Accepted values are `postgres`, `cassandra`, and `off`. + +**Default:** `postgres` + +--- + + +#### PostgreSQL settings + +name | description | default +-------|--------------|---------- +**pg_host** | Host of the PostgreSQL server. | `127.0.0.1` +**pg_port** | Port of the PostgreSQL server. | `5432` +**pg_timeout** | Defines the timeout (in ms), for connecting, reading and writing. | `5000` +**pg_user** | PostgreSQL user. | `kong` +**pg_password** | PostgreSQL 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. Because PostgreSQL uses the same port for TLS and non-TLS, this is only a hint. If the server does not support TLS, the established connection will be a plain one. | `off` +**pg_ssl_version** | When using ssl between Kong and PostgreSQL, the version of tls to use. Accepted values are `tlsv1`, `tlsv1_2`, or `tlsv1_3`. | `tlsv1` +**pg_ssl_required** | When `pg_ssl` is on this determines if TLS must be used between Kong and PostgreSQL. It aborts the connection if the server does not support SSL connections. | `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` +**pg_ssl_cert** | The absolute path to the PEM encoded client TLS certificate for the PostgreSQL connection. Mutual TLS authentication against PostgreSQL is only enabled if this value is set. | none +**pg_ssl_cert_key** | If `pg_ssl_cert` is set, the absolute path to the PEM encoded client TLS private key for the PostgreSQL connection. | none +**pg_max_concurrent_queries** | Sets the maximum number of concurrent queries that can be executing at any given time. This limit is enforced per worker process; the total number of concurrent queries for this node will be will be: `pg_max_concurrent_queries * nginx_worker_processes`. The default value of 0 removes this concurrency limitation. | `0` +**pg_semaphore_timeout** | Defines the timeout (in ms) after which PostgreSQL query semaphore resource acquisition attempts will fail. Such failures will generally result in the associated proxy or Admin API request failing with an HTTP 500 status code. Detailed discussion of this behavior is available in the online documentation. | `60000` +**pg_keepalive_timeout** | Defines the time in milliseconds that an idle connection to PostreSQL server will be kept alive. | `60000` +**pg_ro_host** | Same as `pg_host`, but for the read-only connection. **Note:** Refer to the documentation section above for detailed usage. | none +**pg_ro_port** | Same as `pg_port`, but for the read-only connection. | `` +**pg_ro_timeout** | Same as `pg_timeout`, but for the read-only connection. | `` +**pg_ro_user** | Same as `pg_user`, but for the read-only connection. | `` +**pg_ro_password** | Same as `pg_password`, but for the read-only connection. | `` +**pg_ro_database** | Same as `pg_database`, but for the read-only connection. | `` +**pg_ro_schema** | Same as `pg_schema`, but for the read-only connection. | `` +**pg_ro_ssl** | Same as `pg_ssl`, but for the read-only connection. | `` +**pg_ro_ssl_required** | Same as `pg_ssl_required`, but for the read-only connection. | `` +**pg_ro_ssl_verify** | Same as `pg_ssl_verify`, but for the read-only connection. | `` +**pg_ro_ssl_version** | Same as `pg_ssl_version`, but for the read-only connection. | `` +**pg_ro_max_concurrent_queries** | Same as `pg_max_concurrent_queries`, but for the read-only connection. Note: read-only concurrency is not shared with the main (read-write) connection. | `` +**pg_ro_semaphore_timeout** | Same as `pg_semaphore_timeout`, but for the read-only connection. | `` +**pg_ro_keepalive_timeout** | Same as `pg_keepalive_timeout`, but for the read-only connection. | `` + +#### Cassandra settings + + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + + +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_write_consistency** | Consistency setting to use when writing to the Cassandra cluster. | `ONE` +**cassandra_read_consistency** | Consistency setting to use when reading from 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_refresh_frequency** | Frequency (in seconds) at which the cluster topology will be checked for new or decommissioned nodes. A value of `0` will disable this check, and the cluster topology will never be refreshed. | `60` +**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` + +#### declarative_config + +The path to the declarative configuration file which holds the specification of +all entities (Routes, Services, Consumers, etc.) to be used when the `database` +is set to `off`. + +Entities are stored in Kong's in-memory cache, so you must ensure that enough +memory is allocated to it via the `mem_cache_size` property. You must also +ensure that items in the cache never expire, which means that `db_cache_ttl` +should preserve its default value of 0. + +If the Hybrid mode `role` is set to `data_plane` and there's no configuration +cache file, this configuration is used before connecting to the Control Plane +node as a user-controlled fallback. + +**Default:** none + +--- + +#### declarative_config_string + +The declarative configuration as a string + +**Default:** none + +--- + + +### 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 you do +not configure `db_cache_neg_ttl`. + +If set to 0 (default), such cached entities or misses never expire. + +**Default:** `0` + +--- + +#### db_cache_neg_ttl + +Time-to-live (in seconds) of a datastore miss (no entity). + +If not specified (default), `db_cache_ttl` value will be used instead. + +If set to 0, misses will never expire. + +**Default:** none + +--- + +#### 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` + +--- + +#### db_cache_warmup_entities + +Entities to be pre-loaded from the datastore into the in-memory cache at Kong +start-up. + +This speeds up the first access of endpoints that use the given entities. + +When the `services` entity is configured for warmup, the DNS entries for values +in its `host` attribute are pre-resolved asynchronously as well. + +Cache size set in `mem_cache_size` should be set to a value large enough to +hold all instances of the specified entities. + +If the size is insufficient, Kong will log a warning. + +**Default:** `services` + +--- + + +### 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 load balance 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_cache_size + +Defines the maximum allowed number of DNS records stored in memory cache. + +Least recently used DNS records are discarded from cache if it is full. Both +errors and data are cached, therefore a single name query can easily take up +10-15 slots. + +**Default:** `10000` + +--- + +#### 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` + +--- + + +### Tuning & Behavior section + +#### worker_consistency + +Defines whether this node should rebuild its state synchronously or +asynchronously (the balancers and the router are rebuilt on updates that affects +them, e.g., updates to Routes, Services or Upstreams, via the Admin API or +loading a declarative configuration file). + +Accepted values are: + +- `strict`: the router will be rebuilt synchronously, causing incoming requests + to be delayed until the rebuild is finished. +- `eventual`: the router will be rebuilt asynchronously via a recurring + background job running every second inside of each worker. + +Note that `strict` ensures that all workers of a given node will always proxy +requests with an identical router, but that increased long tail latency can be +observed if frequent Routes and Services updates are expected. + +Using `eventual` will help preventing long tail latency issues in such cases, +but may cause workers to route requests differently for a short period of time +after Routes and Services updates. + +**Default:** `strict` + +--- + +#### worker_state_update_frequency + +Defines how often the worker state changes are checked with a background job. +When a change is detected, a new router or balancer will be built, as needed. +Raising this value will decrease the load on database servers and result in less +jitter in proxy latency, but it might take more time to propagate changes to +each individual worker. + +**Default:** `5` + +--- + + +### 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 + +Comma-separated list of paths to certificate authority files for Lua cosockets +in PEM format. + +The special value `system` attempts to search for the "usual default" provided +by each distro, according to an arbitrary heuristic. In the current +implementation, The following pathnames will be tested in order, and the first +one found will be used: + +- /etc/ssl/certs/ca-certificates.crt (Debian/Ubuntu/Gentoo) +- /etc/pki/tls/certs/ca-bundle.crt (Fedora/RHEL 6) +- /etc/ssl/ca-bundle.pem (OpenSUSE) +- /etc/pki/tls/cacert.pem (OpenELEC) +- /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem (CentOS/RHEL 7) +- /etc/ssl/cert.pem (OpenBSD, Alpine) + +If no file is found on any of these paths, an error will be raised. + +`system` can be used by itself or in conjunction with other CA filepaths. + +When `pg_ssl_verify` or `cassandra_ssl_verify` are enabled, these certificate +authority files will be used for verifying Kong's database connections. + +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. + +If the maximum depth is reached before reaching the end of the chain, +verification will fail. This helps mitigate certificate based DoS attacks. + +See https://github.com/openresty/lua-nginx-module#lua_ssl_verify_depth + +**Default:** `1` + +--- + +#### lua_ssl_protocols + +Defines the TLS versions supported when handshaking with OpenResty's TCP +cosocket APIs. + +This affects connections made by Lua code, such as connections to the database +Kong uses, or when sending logs using a logging plugin. It does *not* affect +connections made to the upstream Service or from downstream clients. + +**Default:** `TLSv1.1 TLSv1.2 TLSv1.3` + +--- + +#### 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` + +--- + +#### enforce_rbac +{:.badge .enterprise} + +Specifies whether Admin API RBAC is enforced. + +Accepts one of `entity`, `both`, `on`, or `off`. + +- `on`: only endpoint-level authorization is enforced. +- `entity`: entity-level authorization applies. +- `both`: enables both endpoint and entity-level authorization. +- `off`: disables both endpoint and entity-level authorization. + +When enabled, Kong will deny requests to the Admin API when a nonexistent or +invalid RBAC authorization token is passed, or the RBAC user with which the +token is associated does not have permissions to access/modify the requested +resource. + +**Default:** `off` + +--- + +#### rbac_auth_header +{:.badge .enterprise} + +Defines the name of the HTTP request header from which the Admin API will +attempt to authenticate the RBAC user. + +**Default:** `Kong-Admin-Token` + +--- + +#### event_hooks_enabled +{:.badge .enterprise} + +When enabled, event hook entities represent a relationship between an event +(source and event) and an action (handler). Similar to web hooks, event hooks +can be used to communicate Kong Gateway service events. When a particular event +happens on a service, the event hook calls a URL with information about that +event. Event hook configurations differ depending on the handler. The events +that are triggered send associated data. + +See: https://docs.konghq.com/enterprise/latest/admin-api/event-hooks/reference/ + +**Default:** `on` + +--- + + +### Kong Manager section + +The Admin GUI for Kong Enterprise. + +--- + +#### admin_gui_listen +{:.badge .free} + +Kong Manager Listeners + +Comma-separated list of addresses and ports on which Kong will expose Kong +Manager. This web application lets you configure and manage Kong, and therefore +should be kept secured. + +Suffixes can be specified for each pair, similarly to the `admin_listen` +directive. + +**Default:** `0.0.0.0:8002, 0.0.0.0:8445 ssl` + +--- + +#### admin_gui_url +{:.badge .free} + +Kong Manager URL + +The lookup, or balancer, address for Kong Manager. + +Accepted format (items in parentheses are optional): + +`://(:(/))` + +Examples: + +- `http://127.0.0.1:8003` +- `https://kong-admin.test` +- `http://dev-machine/dev-285` + +By default, Kong Manager will use the window request host and append the +resolved listener port depending on the requested protocol. + +**Default:** none + +--- + +#### admin_gui_ssl_cert +{:.badge .free} + +The absolute path to the SSL certificate for `admin_gui_listen` values with SSL +enabled. + +**Default:** none + +--- + +#### admin_gui_ssl_cert_key +{:.badge .free} + +The absolute path to the SSL key for `admin_gui_listen` values with SSL +enabled. + +**Default:** none + +--- + +#### admin_gui_flags +{:.badge .free} + +Alters the layout Admin GUI (JSON) The only supported value is `{ +"IMMUNITY_ENABLED": true }` to enable Kong Immunity in the Admin GUI. + +**Default:** `{}` + +--- + +#### admin_gui_access_log +{:.badge .free} + +Kong Manager Access Logs + +Here you can set an absolute or relative path for Kong Manager access logs. +When the path is relative, logs are placed in the `prefix` location. + +Setting this value to `off` disables access logs for Kong Manager. + +**Default:** `logs/admin_gui_access.log` + +--- + +#### admin_gui_error_log +{:.badge .free} + +Kong Manager Error Logs + +Here you can set an absolute or relative path for Kong Manager access logs. +When the path is relative, logs are placed in the `prefix` location. + +Setting this value to `off` disables error logs for Kong Manager. + +Granularity can be adjusted through the `log_level` directive. + +**Default:** `logs/admin_gui_error.log` + +--- + +#### admin_gui_auth +{:.badge .enterprise} + +Kong Manager Authentication Plugin Name + +Secures access to Kong Manager by specifying an authentication plugin to use. + +Supported Plugins: + +- `basic-auth`: Basic Authentication plugin +- `ldap-auth-advanced`: LDAP Authentication plugin +- `openid-connect`: OpenID Connect Authentication plugin + +**Default:** none + +--- + +#### admin_gui_auth_conf +{:.badge .enterprise} + +Kong Manager Authentication Plugin Config (JSON) + +Specifies the configuration for the authentication plugin specified in +`admin_gui_auth`. + +For information about Plugin Configuration consult the associated plugin +documentation. + +Example for `basic-auth`: + +`admin_gui_auth_conf = { "hide_credentials": true }` + +**Default:** none + +--- + +#### admin_gui_auth_password_complexity +{:.badge .enterprise} + +Kong Manager Authentication Password Complexity (JSON) + +When `admin_gui_auth = basic-auth`, this property defines the rules required +for Kong Manager passwords. Choose from preset rules or write your own. + +Example using preset rules: + +`admin_gui_auth_password_complexity = { "kong-preset": "min_8" }` + +All values for kong-preset require the password to contain characters from at +least three of the following categories: + +1. Uppercase characters (A through Z) + +2. Lowercase characters (a through z) + +3. Base-10 digits (0 through 9) + +4. Special characters (for example, &, $, #, %) + +Supported preset rules: + +- `min_8`: minimum length of 8 +- `min_12`: minimum length of 12 +- `min_20`: minimum length of 20 + +To write your own rules, see +https://manpages.debian.org/jessie/passwdqc/passwdqc.conf.5.en.html. + +NOTE: Only keywords "min", "max" and "passphrase" are supported. + +Example: + +`admin_gui_auth_password_complexity = { "min": "disabled,24,11,9,8" }` + +**Default:** none + +--- + +#### admin_gui_session_conf +{:.badge .enterprise} + +Kong Manager Session Config (JSON) + +Specifies the configuration for the Session plugin as used by Kong Manager. + +For information about plugin configuration, consult the Kong Session plugin +documentation. + +Example: + +``` +admin_gui_session_conf = { "cookie_name": "kookie", \ + "secret": "changeme" } +``` + +**Default:** none + +--- + +#### admin_gui_auth_header +{:.badge .enterprise} + +Defines the name of the HTTP request header from which the Admin API will +attempt to identify the Kong Admin user. + +**Default:** `Kong-Admin-User` + +--- + +#### admin_gui_auth_login_attempts +{:.badge .enterprise} + +Number of times a user can attempt to login to Kong Manager. 0 means infinite +attempts allowed. + +**Default:** `0` + +--- + +#### admin_gui_header_txt +{:.badge .free} + +Kong Manager Header Text Sets text for Kong Manager Header Banner. Header +Banner is not shown if this config is empty. + +**Default:** none + +--- + +#### admin_gui_header_bg_color +{:.badge .free} + +Kong Manager Header Background Color Sets background color for Kong Manager +Header Banner Accepts css color keyword, #-hexadecimal or rgb format. Invalid +values are ignored by Manager. + +**Default:** none + +--- + +#### admin_gui_header_txt_color +{:.badge .free} + +Kong Manager Header Text Color Sets text color for Kong Manager Header Banner. + +Accepts css color keyword, #-hexadecimal or rgb format. Invalid values are +ignored by Kong Manager. + +**Default:** none + +--- + +#### admin_gui_footer_txt +{:.badge .free} + +Kong Manager Footer Text Sets text for Kong Manager Footer Banner. Footer +Banner is not shown if this config is empty + +**Default:** none + +--- + +#### admin_gui_footer_bg_color +{:.badge .free} + +Kong Manager Footer Background Color Sets background color for Kong Manager +Footer Banner. + +Accepts css color keyword, #-hexadecimal or rgb format. Invalid values are +ignored by Manager. + +**Default:** none + +--- + +#### admin_gui_footer_txt_color +{:.badge .free} + +Kong Manager Footer Text Color Sets text color for Kong Manager Footer Banner. + +Accepts css color keyword, #-hexadecimal or rgb format. Invalid values are +ignored by Kong Manager. + +**Default:** none + +--- + +#### admin_gui_login_banner_title +{:.badge .free} + +Kong Manager Login Banner Title Text Sets title text for Kong Manager Login +Banner. + +Login Banner is not shown if both `admin_gui_login_banner_title` and +`admin_gui_login_banner_body` are empty. + +**Default:** none + +--- + +#### admin_gui_login_banner_body +{:.badge .free} + +Kong Manager Login Banner Body Text Sets body text for Kong Manager Login +Banner. + +Login Banner is not shown if both `admin_gui_login_banner_title` and +`admin_gui_login_banner_body` are empty. + +**Default:** none + +--- + + +### Vitals section + +#### vitals +{:.badge .enterprise} + +When enabled, Kong will store and report metrics about its performance. + +When running Kong in a multi-node setup, `vitals` entails two separate meanings +depending on the node. + +On a Proxy-only node, `vitals` determines whether to collect data for Vitals. + +On an Admin-only node, `vitals` determines whether to display Vitals metrics +and visualizations on the dashboard. + +**Default:** `on` + +--- + +#### vitals_strategy +{:.badge .enterprise} + +Determines whether to use the Kong database (either PostgreSQL or Cassandra, as +defined by the `database` config value above), or a separate storage engine, for +Vitals metrics. + +Accepted values are `database`, `prometheus`, or `influxdb`. + +**Default:** `database` + +--- + +#### vitals_tsdb_address +{:.badge .enterprise} + +Defines the host and port of the TSDB server to which Vitals data is written +and read. + +This value is only applied when the `vitals_strategy` option is set to +`prometheus` or `influxdb`. This value accepts IPv4, IPv6, and hostname values. + +If the `vitals_strategy` is set to `prometheus`, this value determines the +address of the Prometheus server from which Vitals data will be read. For +`influxdb` strategies, this value controls both the read and write source for +Vitals data. + +**Default:** none + +--- + +#### vitals_tsdb_user +{:.badge .enterprise} + +Influxdb user + +**Default:** none + +--- + +#### vitals_tsdb_password +{:.badge .enterprise} + +Influxdb password + +**Default:** none + +--- + +#### vitals_statsd_address +{:.badge .enterprise} + +Defines the host and port (and an optional protocol) of the StatsD server to +which Kong should write Vitals metrics. This value is only applied when the +`vitals_strategy` is set to `prometheus`. This value accepts IPv4, IPv6, and, +hostnames. Additionally, the suffix `tcp` can be specified; doing so will result +in Kong sending StatsD metrics via TCP instead of the UDP (default). + +**Default:** none + +--- + +#### vitals_statsd_prefix +{:.badge .enterprise} + +Defines the prefix value attached to all Vitals StatsD events. This prefix is +useful when writing metrics to a multi-tenant StatsD exporter or server. + +**Default:** `kong` + +--- + +#### vitals_statsd_udp_packet_size +{:.badge .enterprise} + +Defines the maximum buffer size in which Vitals statsd metrics will be held and +sent in batches. + +This value is defined in bytes. + +**Default:** `1024` + +--- + +#### vitals_prometheus_scrape_interval +{:.badge .enterprise} + +Defines the scrape_interval query parameter sent to the Prometheus server when +reading Vitals data. + +This should be same as the scrape interval (in seconds) of the Prometheus +server. + +**Default:** `5` + +--- + + +### Developer Portal section + +#### portal +{:.badge .enterprise} + +Developer Portal Switch + +When enabled: + +Kong will expose the Dev Portal interface and read-only APIs on the +`portal_gui_listen` address, and endpoints on the Admin API to manage assets. + +When enabled along with `portal_auth`: + +Kong will expose management endpoints for developer accounts on the Admin API +and the Dev Portal API. + +**Default:** `off` + +--- + +#### portal_gui_listen +{:.badge .enterprise} + +Developer Portal GUI Listeners + +Comma-separated list of addresses on which Kong will expose the Developer +Portal GUI. Suffixes can be specified for each pair, similarly to the +`admin_listen` directive. + +**Default:** `0.0.0.0:8003, 0.0.0.0:8446 ssl` + +--- + +#### portal_gui_protocol +{:.badge .enterprise} + +Developer Portal GUI protocol + +The protocol used in conjunction with `portal_gui_host` to construct the +lookup, or balancer address for your Kong Proxy nodes. + +Examples: `http`,`https` + +**Default:** `http` + +--- + +#### portal_gui_host +{:.badge .enterprise} + +Developer Portal GUI host + +The host used in conjunction with `portal_gui_protocol` to construct the +lookup, or balancer address for your Kong Proxy nodes. + +Examples: + +- `:` -> `portal_gui_host = 127.0.0.1:8003` +- `` -> `portal_gui_host = portal_api.domain.tld` + +**Default:** `127.0.0.1:8003` + +--- + +#### portal_cors_origins +{:.badge .enterprise} + +Developer Portal CORS Origins + +A comma separated list of allowed domains for `Access-Control-Allow-Origin` +header. This can be used to resolve CORS issues in custom networking +environments. + +Examples: + +- list of domains: `portal_cors_origins = http://localhost:8003, + https://localhost:8004` +- single domain: `portal_cors_origins = http://localhost:8003` +- all domains: `portal_cors_origins = *` + +NOTE: In most cases, the Developer Portal is able to derive valid CORS origins +by using `portal_gui_protocol`, `portal_gui_host`, and if applicable, +`portal_gui_use_subdomains`. In these cases, `portal_cors_origins` is not needed +and can remain unset. + +**Default:** none + +--- + +#### portal_gui_use_subdomains +{:.badge .enterprise} + +Developer Portal GUI subdomain toggle + +By default Kong Portal uses the first namespace in the request path to +determine workspace. By turning `portal_gui_subdomains` on, Kong Portal will +expect workspace to be included in the request url as a subdomain. + +Example (off): - `:////` -> +`http://kong-portal.com/example-workspace/index` + +Example (on): - `://.` -> +`http://example-workspace.kong-portal.com/index` + +**Default:** `off` + +--- + +#### portal_gui_ssl_cert +{:.badge .enterprise} + +Developer Portal GUI SSL Certificate + +The absolute path to the SSL certificate for `portal_gui_listen` values with +SSL enabled. + +**Default:** none + +--- + +#### portal_gui_ssl_cert_key +{:.badge .enterprise} + +Developer Portal GUI SSL Certificate Key + +The absolute path to the SSL key for `portal_gui_listen` values with SSL +enabled. + +**Default:** none + +--- + +#### portal_gui_access_log +{:.badge .enterprise} + +Developer Portal GUI Access Log location + +Here you can set an absolute or relative path for your Portal GUI access logs. + +Setting this value to `off` will disable logging Portal GUI access logs. + +When using relative pathing, logs will be placed under the `prefix` location. + +**Default:** `logs/portal_gui_access.log` + +--- + +#### portal_gui_error_log +{:.badge .enterprise} + +Developer Portal GUI Error Log location + +Here you can set an absolute or relative path for your Portal GUI error logs. + +Setting this value to `off` will disable logging Portal GUI error logs. + +When using relative pathing, logs will be placed under the `prefix` location. + +Granularity can be adjusted through the `log_level` directive. + +**Default:** `logs/portal_gui_error.log` + +--- + +#### portal_api_listen +{:.badge .enterprise} + +Developer Portal API Listeners + +Comma-separated list of addresses on which Kong will expose the Developer +Portal API. Suffixes can be specified for each pair, similarly to the +`admin_listen` directive. + +**Default:** `0.0.0.0:8004, 0.0.0.0:8447 ssl` + +--- + +#### portal_api_url +{:.badge .enterprise} + +Developer Portal API URL + +The lookup, or balancer, address for your Developer Portal nodes. + +This value is commonly used in a microservices or service-mesh oriented +architecture. + +`portal_api_url` is the address on which your Kong Dev Portal API is accessible +by Kong. You should only set this value if your Kong Dev Portal API lives on a +different node than your Kong Proxy. + +Accepted format (parts in parenthesis are optional): + +`://(:(/))` + +Examples: + +- `://:` -> `portal_api_url = http://127.0.0.1:8003` +- `SSL ://` -> `portal_api_url = + https://portal_api.domain.tld` +- `:///` -> `portal_api_url = + http://dev-machine/dev-285` + +By default this value points to the local interface: + +- `http://0.0.0.0:8004` + +**Default:** none + +--- + +#### portal_api_ssl_cert +{:.badge .enterprise} + +Developer Portal API SSL Certificate + +The absolute path to the SSL certificate for `portal_api_listen` values with +SSL enabled. + +**Default:** none + +--- + +#### portal_api_ssl_cert_key +{:.badge .enterprise} + +Developer Portal API SSL Certificate Key + +The absolute path to the SSL key for `portal_api_listen` values with SSL +enabled. + +**Default:** none + +--- + +#### portal_api_access_log +{:.badge .enterprise} + +Developer Portal API Access Log location + +Here you can set an absolute or relative path for your Portal API access logs. + +Setting this value to `off` will disable logging Portal API access logs. + +When using relative pathing, logs will be placed under the `prefix` location. + +**Default:** `logs/portal_api_access.log` + +--- + +#### portal_api_error_log +{:.badge .enterprise} + +Developer Portal API Error Log location + +Here you can set an absolute or relative path for your Portal API error logs. + +Setting this value to `off` will disable logging Portal API error logs. + +When using relative pathing, logs will be placed under the `prefix` location. + +Granularity can be adjusted through the `log_level` directive. + +**Default:** `logs/portal_api_error.log` + +--- + +#### portal_is_legacy +{:.badge .enterprise} + +Developer Portal legacy support + +Setting this value to `on` will cause all new portals to render using the +legacy rendering system by default. + +Setting this value to `off` will cause all new portals to render using the +current rendering system. + +**Default:** `off` + +--- + +#### portal_app_auth +{:.badge .enterprise} + +Developer Portal application registration auth provider and strategy. Must be +set to enable application_registration plugin Currently accepts kong-oauth2 or +external-oauth2 + +**Default:** `kong-oauth2` + +--- + + +### Default Developer Portal Authentication section + +Referenced on workspace creation to set Dev Portal authentication defaults in +the database for that particular workspace. + +--- + +#### portal_auth +{:.badge .enterprise} + +Developer Portal Authentication Plugin Name + +Specifies the authentication plugin to apply to your Developer Portal. +Developers will use the specified form of authentication to request access, +register, and login to your Developer Portal. + +Supported Plugins: + +- Basic Authentication: `portal_auth = basic-auth` +- OIDC Authentication: `portal_auth = openid-connect` + +**Default:** none + +--- + +#### portal_auth_password_complexity +{:.badge .enterprise} + +Kong Portal Authentication Password Complexity (JSON) + +When portal_auth = basic-auth, this property defines the rules required for +Kong Portal passwords. Choose from preset rules or write your own. + +Example using preset rules: + +`portal_auth_password_complexity = { "kong-preset": "min_8" }` + +All values for kong-preset require the password to contain characters from at +least three of the following categories: + +1. Uppercase characters (A through Z) + +2. Lowercase characters (a through z) + +3. Base-10 digits (0 through 9) + +4. Special characters (for example, &, $, #, %) + +Supported preset rules: + +- `min_8`: minimum length of 8 +- `min_12`: minimum length of 12 +- `min_20`: minimum length of 20 + +To write your own rules, see +https://manpages.debian.org/jessie/passwdqc/passwdqc.conf.5.en.html. + +NOTE: Only keywords "min", "max" and "passphrase" are supported. + +Example: + +`portal_auth_password_complexity = { "min": "disabled,24,11,9,8" }` + +**Default:** none + +--- + +#### portal_auth_conf +{:.badge .enterprise} + +Developer Portal Authentication Plugin Config (JSON) + +Specifies the plugin configuration object in JSON format to be applied to your +Developer Portal authentication. + +For information about Plugin Configuration consult the associated plugin +documentation. + +Example for `basic-auth`: + +`portal_auth_conf = { "hide_credentials": true }` + +**Default:** none + +--- + +#### portal_auth_login_attempts +{:.badge .enterprise} + +Number of times a user can attempt to login to the Dev Portal before password +must be reset. + +0 (default) means infinite attempts allowed. + +Note: Any value greater than 0 will only affect Dev Portals secured with +basic-auth. + +**Default:** `0` + +--- + +#### portal_session_conf +{:.badge .enterprise} + +Portal Session Config (JSON) + +Specifies the configuration for the Session plugin as used by Kong Portal. + +For information about Plugin Configuration consult the Kong Session Plugin +documentation. + +Example: + +``` +portal_session_conf = { "cookie_name": "portal_session", \ + "secret": "changeme", \ + "storage": "kong" } +``` + +**Default:** none + +--- + +#### portal_auto_approve +{:.badge .enterprise} + +Developer Portal Auto Approve Access + +When this flag is set to `on`, a developer will automatically be marked as +"approved" after completing registration. Access can still be revoked through +the Admin GUI or API. + +**Default:** `off` + +--- + +#### portal_token_exp +{:.badge .enterprise} + +Duration in seconds for the expiration of portal login reset/account validation +token. + +**Default:** `21600` + +--- + +#### portal_email_verification +{:.badge .enterprise} + +Portal Developer Email Verification. + +When enabled Developers will receive an email upon registration to verify their +account. Developers will not be able to use the Developer Portal until they +verify their account. + +Note: SMTP must be turned on in order to use this feature. + +**Default:** `off` + +--- + + +### Default Portal Smtp Configuration section + +Referenced on workspace creation to set SMTP defaults in the database for that +particular workspace. + +--- + +#### portal_invite_email +{:.badge .enterprise} + +Enable or disable portal_invite_email + +**Default:** `on` + +--- + +#### portal_access_request_email +{:.badge .enterprise} + +Enable or disable portal_access_request_email + +**Default:** `on` + +--- + +#### portal_approved_email +{:.badge .enterprise} + +Enable or disable portal_approved_email + +**Default:** `on` + +--- + +#### portal_reset_email +{:.badge .enterprise} + +Enable or disable portal_reset_email + +**Default:** `on` + +--- + +#### portal_reset_success_email +{:.badge .enterprise} + +Enable or disable portal_reset_success_email + +**Default:** `on` + +--- + +#### portal_emails_from +{:.badge .enterprise} + +The name and email address for the `From` header for portal emails + +Example: `portal_emails_from = Your Name ` + +Note: Some SMTP servers will not use this value, but instead insert the email +and name associated with the account. + +**Default:** none + +--- + +#### portal_emails_reply_to +{:.badge .enterprise} + +Email address for the `Reply-To` header for portal emails + +Example: `portal_emails_reply_to = example@example.com` + +Note: Some SMTP servers will not use this value, but instead insert the email +associated with the account. + +**Default:** none + +--- + + +### Admin Smtp Configuration section + +#### admin_emails_from +{:.badge .enterprise} + +The email address for the `From` header for admin emails. + +**Default:** `""` + +--- + +#### admin_emails_reply_to +{:.badge .enterprise} + +Email address for the `Reply-To` header for admin emails. + +**Default:** none + +--- + +#### admin_invitation_expiry +{:.badge .enterprise} + +Expiration time for the admin invitation link (in seconds). 0 means no +expiration. + +Example, 72 hours: `72 * 60 * 60 = 259200` + +**Default:** `259200` + +--- + + +### General Smtp Configuration section + +#### smtp_mock +{:.badge .enterprise} + +This flag will mock the sending of emails. This can be used for testing before +the SMTP client is fully configured. + +**Default:** `on` + +--- + +#### smtp_host +{:.badge .enterprise} + +The hostname of the SMTP server to connect to. + +**Default:** `localhost` + +--- + +#### smtp_port +{:.badge .enterprise} + +The port number on the SMTP server to connect to. + +**Default:** `25` + +--- + +#### smtp_starttls +{:.badge .enterprise} + +When set to `on`, STARTTLS is used to encrypt communication with the SMTP +server. This is normally used in conjunction with port 587. + +**Default:** `off` + +--- + +#### smtp_username +{:.badge .enterprise} + +Username used for authentication with SMTP server + +**Default:** none + +--- + +#### smtp_password +{:.badge .enterprise} + +Password used for authentication with SMTP server + +**Default:** none + +--- + +#### smtp_ssl +{:.badge .enterprise} + +When set to `on`, SMTPS is used to encrypt communication with the SMTP server. +This is normally used in conjunction with port 465. + +**Default:** `off` + +--- + +#### smtp_auth_type +{:.badge .enterprise} + +The method used to authenticate with the SMTP server Valid options are `plain`, +`login`, or `nil` + +**Default:** none + +--- + +#### smtp_domain +{:.badge .enterprise} + +The domain used in the `EHLO` connection and part of the `Message-ID` header + +**Default:** `localhost.localdomain` + +--- + +#### smtp_timeout_connect +{:.badge .enterprise} + +The timeout (in milliseconds) for connecting to the SMTP server. + +**Default:** `60000` + +--- + +#### smtp_timeout_send +{:.badge .enterprise} + +The timeout (in milliseconds) for sending data to the SMTP server. + +**Default:** `60000` + +--- + +#### smtp_timeout_read +{:.badge .enterprise} + +The timeout (in milliseconds) for reading data from the SMTP server. + +**Default:** `60000` + +--- + +#### smtp_admin_emails +{:.badge .enterprise} + +Comma separated list of admin emails to receive notifications. + +Example `admin1@example.com, admin2@example.com` + +**Default:** none + +--- + + +### Data & Admin Audit section + +When enabled, Kong will store detailed audit data regarding Admin API and +database access. In most cases, updates to the database are associated with +Admin API requests. As such, database object audit log data is tied to a given +HTTP via a unique identifier, providing built-in association of Admin API and +database traffic. + +--- + +#### audit_log + +When enabled, Kong will log information about Admin API access and database row +insertions, updates, and deletes. + +**Default:** `off` + +--- + +#### audit_log_ignore_methods + +Comma-separated list of HTTP methods that will not generate audit log entries. +By default, all HTTP requests will be logged. + +**Default:** none + +--- + +#### audit_log_ignore_paths + +Comma-separated list of request paths that will not generate audit log entries. +By default, all HTTP requests will be logged. + +**Default:** none + +--- + +#### audit_log_ignore_tables + +Comma-separated list of database tables that will not generate audit log +entries. By default, updates to all database tables will be logged (the term +"updates" refers to the creation, update, or deletion of a row). + +**Default:** none + +--- + +#### audit_log_payload_exclude + +Comma-separated list of keys that will be filtered out of the payload. Keys +that were filtered will be recorded in the audit log. + +**Default:** `token, secret, password` + +--- + +#### audit_log_record_ttl + +Length, in seconds, of the TTL for audit log records. Records in the database +older than their TTL are automatically purged. + +Example, 30 days: `30 * 24 * 60 * 60 = 2592000` + +**Default:** `2592000` + +--- + +#### audit_log_signing_key + +Defines the path to a private RSA signing key that can be used to insert a +signature of audit records, adjacent to the record. The corresponding public key +should be stored offline, and can be used the validate audit entries in the +future. If this value is undefined, no signature will be generated. + +**Default:** none + +--- + + +### Granular Tracing section + +Granular tracing offers a mechanism to expose metrics and detailed debug data +about the lifecycle of Kong in a human- or machine-consumable format. + +--- + +#### tracing +{:.badge .enterprise} + +When enabled, Kong will generate granular debug data about various portions of +the request lifecycle, such as DB or DNS queries, plugin execution, core handler +timing, etc. + +**Default:** `off` + +--- + +#### tracing_write_strategy +{:.badge .enterprise} + +Defines how Kong will write tracing data at the conclusion of the request. The +default option, `file`, writes a human-readable depiction of tracing data to a +configurable location on the node's file system. Other strategies write tracing +data as a JSON document to the configured endpoint. Valid entries for this +option are `file`, `file_raw`, `http`, `tcp`, `tls`, and `udp`. + +**Default:** `file` + +--- + +#### tracing_write_endpoint +{:.badge .enterprise} + +Defines the endpoint to which tracing data will be written. + +- For the `file` and `file_raw` tracing write strategies, this value must be a + valid location on the node's file system to which Kong must have write access. +- For the `tcp`, `tls`, and `udp` strategies, this value is defined as a string + in the form of: `:` +- For the `http` strategy, this value is defined in the form of: + `://(:(/))` + +Traces sent via HTTP are delivered via POST method with an `application/json` +Content-Type. + +**Default:** none + +--- + +#### tracing_time_threshold +{:.badge .enterprise} + +The minimum time, in microseconds, over which a trace must execute in order to +write the trace data to the configured endpoint. This configuration can be used +to lower the noise present in trace data by removing trace objects that are not +interesting from a timing perspective. The default value of `0` removes this +limitation, causing traces of any duration to be written. + +**Default:** `0` + +--- + +#### tracing_types +{:.badge .enterprise} + +Defines the types of traces that are written. + +Trace types not defined in this list are ignored, regardless of their lifetime. +The default special value of `all` results in all trace types being written, +regardless of type. + +The following trace types are included: + +- `query`: trace the database query +- `legacy_query`: (deprecated) trace the database query with legacy DAO +- `router`: trace Kong routing the request; internal routing time +- `balancer`: trace the execution of the overall balancer phase +- `balancer.getPeer`: trace Kong selecting an upstream peer from the + ring-balancer +- `balancer.toip`: trace balancer to resolve peer's host to IP +- `connect.toip`: trace cosocket to resolve target's host to IP +- `access.before`: trace the preprocessing of access phase, like parameter + parsing, route matching, and balance preparation +- `access.after`: trace the postprocess of access phase, like balancer + execution and internal variable assigning +- `cassandra_iterate`: trace Cassandra driver to paginate over results +- `plugin`: trace plugins phase handlers + +**Default:** `all` + +--- + +#### tracing_debug_header +{:.badge .enterprise} + +Defines the name of the HTTP request header that must be present in order to +generate traces within a request. Setting this value provides a mechanism to +selectively generate request traces at the client's request. Note that the value +of the header does not matter, only that the header is present in the request. +When this value is not set and tracing is enabled, Kong will generate trace data +for all requests flowing through the proxy and Admin API. Note that data from +certificate handling phases is not logged when this setting is enabled. + +**Default:** none + +--- + +#### generate_trace_details +{:.badge .enterprise} + +When enabled, Kong will write context- specific details into traces. Trace +details offer more data about the context of the trace. This can significantly +increase the size of trace reports. Note also that trace details may contain +potentially sensitive information, such as raw SQL queries; care should be taken +to store traces properly when this option is enabled. + +**Default:** `off` + +--- + + +### Route Collision Detection/Prevention section + +#### route_validation_strategy +{:.badge .enterprise} + +The strategy used to validate routes when creating or updating them. + +Different strategies are available to tune how to enforce splitting traffic of +workspaces. + +- `smart` is the default option and uses the algorithm described in + https://docs.konghq.com/gateway/latest/kong-enterprise/workspaces/ +- `off` disables any check +- `path` enforces routes to comply with the pattern described in config + enforce_route_path_pattern + +**Default:** `smart` + +--- + +#### enforce_route_path_pattern +{:.badge .enterprise} + +Specifies the Lua pattern which will be enforced on the `paths` attribute of a +Route object. You can also add a placeholder for the workspace in the pattern, +which will be rendered during runtime based on the workspace to which the +`route` belongs. + +This setting is only relevant if `route_validation_strategy` is set to `path`. + +Example For Pattern `/$(workspace)/v%d/.*` valid paths are: + +1. `/group1/v1/` if route belongs to workspace `group1`. + +2. `/group2/v1/some_path` if route belongs to workspace `group2`. + +**Default:** none + +--- + + +### Database Encryption & Keyring Management section + +When enabled, Kong will transparently encrypt sensitive fields, such as +Consumer credentials, TLS private keys, and RBAC user tokens, among others. A +full list of encrypted fields is available from the Kong Enterprise +documentation site. + +Encrypted data is transparently decrypted before being displayed to the Admin +API or made available to plugins or core routing logic. + +While this feature is GA, do note that we currently do not provide normal +semantic versioning compatibility guarantees on the keyring feature's APIs in +that Kong may make a breaking change to the feature in a minor version. Also +note that mis-management of keyring data may result in irrecoverable data loss. + +--- + +#### keyring_enabled +{:.badge .enterprise} + +When enabled, Kong will encrypt sensitive field values before writing them to +the database, and subsuquently decrypt them when retrieving data for the Admin +API, Developer Portal, or proxy business logic. Symmetric encryption keys are +managed based on the strategy defined below. + +**Default:** `off` + +--- + +#### keyring_strategy +{:.badge .enterprise} + +Defines the strategy implementation by which Kong nodes will manage symmetric +encryption keys. Please see the Kong Enterprise documentation for a detailed +description of each strategies. Acceptable values for this option are 'cluster' +and 'vault'. + +**Default:** `cluster` + +--- + +#### keyring_public_key +{:.badge .enterprise} + +Defines the filesystem path at which the public key of an RSA keypair resides. +This keypair is used for symmetric keyring import/ export, e.g., for disaster +recovery and optional bootstrapping. + +**Default:** none + +--- + +#### keyring_private_key +{:.badge .enterprise} + +Defines the filesystem path at which the private key of an RSA keypair resides. +This keypair is used for symmetric keyring import/ export, e.g., for disaster +recovery and optional bootstrapping. + +**Default:** none + +--- + +#### keyring_blob_path +{:.badge .enterprise} + +Defines the filesystem path at which Kong will backup the initial keyring +material. + +This option is useful largely for development purposes. + +**Default:** none + +--- + +#### keyring_vault_host +{:.badge .enterprise} + +Defines the Vault host at which Kong will fetch the encryption material. This +value should be defined in the format: + +`://:` + +**Default:** none + +--- + +#### keyring_vault_mount +{:.badge .enterprise} + +Defines the name of the Vault v2 KV secrets engine at which symmetric keys are +found. + +**Default:** none + +--- + +#### keyring_vault_path +{:.badge .enterprise} + +Defines the names of the Vault v2 KV path at which symmetric keys are found. + +**Default:** none + +--- + +#### keyring_vault_token +{:.badge .enterprise} + +Defines the token value used to communicate with the v2 KV Vault HTTP(S) API. + +**Default:** none + +--- + +#### untrusted_lua +{:.badge .enterprise} + +Controls loading of Lua functions from admin-supplied sources such as the Admin +API. LuaJIT bytecode loading is always disabled. + +**Warning:** LuaJIT is not designed as a secure runtime for running malicious +code, therefore you should properly protect your Admin API endpoint even with +sandboxing enabled. The sandbox only provides protection against trivial +attackers or unintentional modification of the Kong global environment. + +Accepted values are: `off`, `sandbox`, or `on`: + +* `off`: Disallow loading of any arbitrary Lua functions. The `off` option +disables any functionality that runs arbitrary Lua code, including the +Serverless Functions plugins and any transformation plugin that allows custom +Lua functions. + +* `sandbox`: Allow loading of Lua functions, but use a sandbox when executing +them. The sandboxed function has restricted access to the global environment and +only has access to standard Lua functions that will generally not cause harm to +the Kong Gateway node. + +* `on`: Functions have unrestricted access to the global environment and can +load any Lua modules. This is similar to the behavior in Kong Gateway prior to +2.3.0. + +The default `sandbox` environment does not allow importing other modules or +libraries, or executing anything at the OS level (for example, file read/write). +The global environment is also not accessible. + +Examples of `untrusted_lua = sandbox` behavior: + +* You can't access or change global values such as +`kong.configuration.pg_password` * You can run harmless lua: `local foo = 1 + +1`. However, OS level functions are not allowed, like: `os.execute('rm -rf +/*')`. + +For a full allowed/disallowed list, see: +https://github.com/kikito/sandbox.lua/blob/master/sandbox.lua + +To customize the sandbox environment, use the `untrusted_lua_sandbox_requires` +and `untrusted_lua_sandbox_environment` parameters below. + +**Default:** `sandbox` + +--- + +#### untrusted_lua_sandbox_requires +{:.badge .enterprise} + +Comma-separated list of modules allowed to be loaded with `require` inside the +sandboxed environment. Ignored if `untrusted_lua` is not `sandbox`. + +For example, say you have configured the Serverless pre-function plugin and it +contains the following `requires`: + +``` +local template = require "resty.template" +local split = require "kong.tools.utils".split +``` + +To run the plugin, add the modules to the allowed list: + +``` +untrusted_lua_sandbox_requires = resty.template, kong.tools.utils +``` + +**Warning:** Allowing certain modules may create opportunities to escape the +sandbox. For example, allowing `os` or `luaposix` may be unsafe. + +**Default:** none + +--- + +#### untrusted_lua_sandbox_environment +{:.badge .enterprise} + +Comma-separated list of global Lua variables that should be made available +inside the sandboxed environment. Ignored if `untrusted_lua` is not `sandbox`. + +**Warning**: Certain variables, when made available, may create opportunities +to escape the sandbox. + +**Default:** none + +--- + + + +[Penlight]: http://stevedonovan.github.io/Penlight/api/index.html +[pl.template]: http://stevedonovan.github.io/Penlight/api/libraries/pl.template.html +[templates]: https://github.com/kong/kong/tree/master/kong/templates diff --git a/app/gateway/2.7.x/reference/db-less-and-declarative-config.md b/app/gateway/2.7.x/reference/db-less-and-declarative-config.md new file mode 100644 index 000000000000..7ad65476fa48 --- /dev/null +++ b/app/gateway/2.7.x/reference/db-less-and-declarative-config.md @@ -0,0 +1,291 @@ +--- +title: DB-less and Declarative Configuration +--- + + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + + +Traditionally, {{site.base_gateway}} has always required a database, to store its configured entities such as Routes, +Services and Plugins. Kong uses its configuration file, `kong.conf`, to +specify the use of PostgreSQL and Cassandra and its various settings. + +{{site.base_gateway}} can be run without a database using only in-memory storage for entities. We call this DB-less mode. When running {{site.base_gateway}} 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 + +## Declarative configuration + +The key idea in declarative configuration is 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 do that". "Declarative" 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 attained 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. + +## Set up Kong in DB-less mode + +To use {{site.base_gateway}} 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`. + +Command: + +``` +http :8001/ +``` + +Sample response: + +``` +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/2.1.0 +{ + "configuration:" { + ... + "database": "off", + ... + }, + ... + "version": "2.1.0" +} +``` + +{{site.base_gateway}} 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. + +Command: + +``` +http :8001/routes +``` + +Sample response: + +``` +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/2.1.0 + +{ + "data": [], + "next": null +} +``` + +## Creating a declarative configuration file + +{:.note} +> **Note:** We recommend using decK to manage your declarative configuration. +See the [decK documentation](/deck/) for more information. + +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. + +## Declarative configuration format + +The {{site.base_gateway}} declarative configuration format consists of lists of +entities and their attributes. This is a small yet complete +example that illustrates a number of features: + +```yaml +_format_version: "2.1" +_transform: true + +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: "2.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. + +The `_transform` metadata is an optional boolean (defaults to `true`), which +controls whether schema transformations will occur while importing. The rule +of thumb for using this field is: if you are importing plain-text credentials +(i.e. passwords), you likely want to set it to `true`, so that Kong will +encrypt/hash them before storing them in the database. If you are importing +**already hashed/encrypted** credentials, set `_transform` to `false` so that +the encryption does not happen twice. + +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 that 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 +``` + +## Check the 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 +``` + +## Load the file + +There are two ways to load a declarative configuration file into Kong: using +`kong.conf` or the Admin API. + +To load a declarative configuration file 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 +``` + +You can also load a declarative configuration file into a running +Kong node with the Admin API, using the `/config` endpoint. The +following example loads `kong.yml` using HTTPie: + +``` +http :8001/config config=@kong.yml +``` + +{:.important} +The `/config` endpoint replaces the entire set of entities in memory +with the ones specified in the given file. + +Or another way you can start Kong in DB-less mode is with a +declarative configuration in a string using the `KONG_DECLARATIVE_CONFIG_STRING` +environment variable. + +``` +export KONG_DATABASE=off +export KONG_DECLARATIVE_CONFIG_STRING='{"_format_version":"1.1", "services":[{"host":"httpbin.konghq.com","port":443,"protocol":"https", "routes":[{"paths":["/"]}]}],"plugins":[{"name":"rate-limiting", "config":{"policy":"local","limit_by":"ip","minute":3}}]}' +kong start +``` + +## 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 or dynamic creation of +entities. + +For current plugin compatibility, see [Plugin compatibility](/hub/plugins/compatibility/). diff --git a/app/gateway/2.7.x/reference/external-plugins.md b/app/gateway/2.7.x/reference/external-plugins.md new file mode 100644 index 000000000000..94320b40cc75 --- /dev/null +++ b/app/gateway/2.7.x/reference/external-plugins.md @@ -0,0 +1,633 @@ +--- +title: Plugins in Other Languages + +--- + +## Introduction + +External plugins are those that run on a process separate from {{site.base_gateway}} itself, +enabling the use of any programming language for which an appropriate +plugin server is available. + +Each plugin server hosts one or more plugins and communicates with the +main {{site.base_gateway}} process through Unix sockets. If so configured, {{site.base_gateway}} can manage +those processes, starting, restarting and stopping as necessary. + +{{site.base_gateway}} currently maintains a Go language plugin server, +[go-pluginserver], the corresponding PDK library +package [go-pdk], the JavaScript language support [kong-js-pdk] +and Python language support [kong-python-pdk]. + +## {{site.base_gateway}} plugin server configuration + +The `pluginserver_names` property is a comma-separated list of names, one +for each plugin server process. These names are used to group each process' +properties and to annotate log entries. + +For each name, other properties can be defined: + +Property | Description | Default +---------|-------------|-------- +`pluginserver__socket` | Unix socket path | `/usr/local/kong/.socket` +`pluginserver__start_cmd` | Command to start the plugin server process | `/usr/local/bin/` +`pluginserver__query_cmd` | Command to dump available plugins' info | `/usr/local/bin/query_` + + +For example, you could set Go and Python plugins like this (assuming +an hypothetical Python plugin server called `pypluginserver.py`): + +``` +pluginserver_names = go,python + +pluginserver_go_socket = /usr/local/kong/go_pluginserver.sock +pluginserver_go_start_cmd = /usr/local/bin/go-pluginserver -kong-prefix /usr/local/kong/ -plugins-directory /usr/local/kong/go-plugins +pluginserver_go_query_cmd = /usr/local/bin/go-pluginserver -dump-all-plugins -plugins-directory /usr/local/kong/go-plugins + +pluginserver_python_socket = /usr/local/kong/python_pluginserver.sock +pluginserver_python_start_cmd = /usr/local/bin/kong-python-pluginserver +pluginserver_python_query_cmd = /usr/local/bin/kong-python-pluginserver --dump-all-plugins +``` + +To enable those plugins, add the each plugin name to the `plugins` config. Assume we have those hello plugins +in each language: + +``` +plugins = bundled, go-hello, js-hello, py-hello +``` + +{:.note} +> **Note:** The `pluginserver_XXX_start_cmd` and `pluginserver_XXX_query_cmd` commands use + a limited default `PATH` variable. In most cases, you have to specify the full executable + path instead. + +### Legacy configuration + +{{site.base_gateway}} versions 2.0.x to 2.2.x supported only Go external plugins and a single +plugin server using a different configuration style. Starting with {{site.base_gateway}} version 2.3, +the old style is recognized and internally transformed to the new style. + +If property `pluginserver_names` isn't defined, the legacy properties +`go_plugins_dir` and `go_pluginserver_exe` are tried: + +Property | Description | Default +---------|-------------|-------- +`go_plugins_dir` | Directory with Go plugins | `off`, meaning to disable Go plugins +`go_pluginserver_exe` | Path to the go-pluginserver executable | `/usr/local/bin/go-pluginserver` + +Notes: + +- The old style doesn't allow multiple plugin servers. +- Version 0.5.0 of [go-pluginserver] requires the old style configuration. +- The new style configuration requires v0.6.0 of [go-pluginserver] + +## Developing Go plugins + +{{site.base_gateway}} support for the Go language consist of two parts: + +- [go-pdk] as a library, provides Go functions to access {{site.base_gateway}} features of the [PDK][kong-pdk]. +- [go-pluginserver] an executable to dynamically load plugins written in Go. + + +Notes: + +The {{site.base_gateway}} version 2.3 allows multiple plugin servers; in particular +it's now possible to write single-plugin servers, in effect plugins as +microservices. To help with this, version v0.6.0 of the [go-pdk] package +includes an optional plugin server. See [Embedded Server](#embedded-server) +for more information. + +The [go-pluginserver] process is still supported. Its main advantage is +that it's a single process for any number of plugins, but the dynamic +loading of plugins has proven challenging under the Go language (unlike +the microservice architecture, which is well supported by the language +and tools). + +### Development + +To write a {{site.base_gateway}} plugin in Go, you need to: + +1. Define a structure type to hold configuration. +2. Write a `New()` function to create instances of your structure. +3. Add methods on that structure to handle phases. + + If you want a dynamically-loaded plugin to be used with [go-pluginserver]: + +4. Compile your Go plugin with `go build -buildmode plugin`. +5. Put the resulting library (the `.so` file) into the `go_plugins_dir` directory. + + If you want a standalone plugin microservice: + +4. Include the `go-pdk/server` sub-library. +5. Add a `main()` function that calls `server.StartServer(New, Version, Priority)`. +6. Compile as an executable with `go build`. + +**Note**: Check out [this repository](https://github.com/Kong/go-plugins) +for example Go plugins. + +#### 1. Configuration Structure + +Plugins written in Lua define a schema to specify how to read and validate +configuration data coming from the datastore or the Admin API. Since Go is a +statically-typed language, all that specification is handled by defining a +configuration structure: + +```go +type MyConfig struct { + Path string + Reopen bool +} +``` + +Public fields (that is, those starting with a capital letter) will be filled +with configuration data. If you want them to have a different name in the +datastore, add field tags as defined in the `encoding/json` package: + +```go +type MyConfig struct { + Path string `json:"my_file_path"` + Reopen bool `json:"reopen"` +} +``` + +#### 2. New() Constructor + +Your plugin must define a function called `New` that creates an instance of this type +and returns as an `interface{}`. In most cases, it’s just this: + +```go +func New() interface{} { + return &MyConfig{} +} +``` + +You can add more fields to the structure and they’ll be passed around, but +there are no guarantees about the lifetime or quantity of configuration +instances. + +#### 3. Phase Handlers + +Similarly to {{site.base_gateway}} Lua plugins, you can implement custom logic to be executed at +various points of the request processing lifecycle. For example, to execute +custom Go code in the access phase, define a function named `Access`: +```go +func (conf *MyConfig) Access (kong *pdk.PDK) { + ... +} +``` + +The phases you can implement custom logic for are as follows, and the expected function +signature is the same for all of them: + +- `Certificate` +- `Rewrite` +- `Access` +- `Response` +- `Preread` +- `Log` + +Similar to Lua plugins, the presence of the `Response` handler automatically enables the buffered proxy mode. + +#### 4. Version and Priority + +Similarly to {{site.base_gateway}} Lua plugins, you can define the version number and priority of execution +by having following lines in plugin code: + +```go +const Version = "1.0.0" +const Priority = 1 +``` + +{{site.base_gateway}} executes plugins from highest priority to lowest ones. + +### Embedded server + +Each plugin can be a microservice, compiled as a standalone executable. + +To use the embedded server, include `github.com/Kong/go-pdk/server` in +the imports list, and add a `main()` function: + +```go +func main () { + server.StartServer(New, Version, Priority) +} +``` + +Note that the `main()` function must have a `package main` line at the +top of the file. + +Then, a standard Go build creates an executable. There are no extra go-pluginserver, +no plugin loading, and no compiler/library/environment compatibility issues. + +The resulting executable can be placed somewhere in your path (for example, +`/usr/local/bin`). The common `-h` flag shows a usage help message: + +``` +$ my-plugin -h + +Usage of my-plugin: + -dump + Dump info about plugins + -help + Show usage info + -kong-prefix string + Kong prefix path (specified by the -p argument commonly used in the Kong CLI) (default "/usr/local/kong") +``` + +When run without arguments, it creates a socket file with the +`kong-prefix` and the executable name, appending `.socket`. For example, +if the executable is `my-plugin`, it would be +`/usr/local/kong/my-plugin.socket` by default. + +#### Example configuration + +Two standalone plugins, called `my-plugin` and `other-one`: + +``` +pluginserver_names = my-plugin,other-one + +pluginserver_my_plugin_socket = /usr/local/kong/my-plugin.socket +pluginserver_my_plugin_start_cmd = /usr/local/bin/my-plugin +pluginserver_my_plugin_query_cmd = /usr/local/bin/my-plugin -dump + +pluginserver_other_one_socket = /usr/local/kong/other-one.socket +pluginserver_other_one_start_cmd = /usr/local/bin/other-one +pluginserver_other_one_query_cmd = /usr/local/bin/other-one -dump + +``` + +Note that the socket and start command settings coincide with +their defaults, so they can be omitted: + +``` +pluginserver_names = my-plugin,other-one +pluginserver_my_plugin_query_cmd = /usr/local/bin/my-plugin -dump +pluginserver_other_one_query_cmd = /usr/local/bin/other-one -dump +``` + +## Developing JavaScript plugins + +{{site.base_gateway}} support for the JavaScript language is provided by [kong-js-pdk]. +The library provides a plugin server to provide runtime for JavaScript plugins, and +functions to access {{site.base_gateway}} features of the [PDK][kong-pdk]. + +TypeScript is also supported in the following ways: + +- [kong-js-pdk] includes type definitions for PDK functions that allow type checking +when developing plugins in TypeScript. +- Plugin written in TypeScript can be loaded directly and transpiled on the fly. + +### Example configuration + +[kong-js-pdk] can be installed using `npm`. To install the plugin server binary globally: + +``` +npm install kong-pdk -g +``` + +Assume the plugins are stored in `/usr/local/kong/js-plugins`: + +``` +pluginserver_names = js +pluginserver_js_socket = /usr/local/kong/js_pluginserver.sock +pluginserver_js_start_cmd = /usr/local/bin/kong-js-pluginserver --plugins-directory /usr/local/kong/js-plugins +pluginserver_js_query_cmd = /usr/local/bin/kong-js-pluginserver --plugins-directory /usr/local/kong/js-plugins --dump-all-plugins +``` + +### Development + +Install [kong-js-pdk] in your local development directory: + +``` +npm install kong-pdk --save +``` + +A valid JavaScript plugin implementation should export the following object: + +```javascript +module.exports = { + Plugin: KongPlugin, + Schema: [ + { message: { type: "string" } }, + ], + Version: '0.1.0', + Priority: 0, +} +``` + +`Plugin` attribute defines the class that implements this plugin. `Schema` defines the config +schema of plugin, it shares the same syntax as it's a Lua plugin. `Version` and `Priority` +defines the version number and priority of execution respectively. + +**Note**: Check out [this repository](https://github.com/Kong/kong-js-pdk/tree/master/examples) +for example JavaScript and TypeScript plugins. + +#### 1. Phase Handlers + +Similarly to {{site.base_gateway}} Lua plugins, you can implement custom logic to be executed at +various points of the request processing lifecycle. For example, to execute +custom JavaScript code in the access phase, define a function named `access`: + +```javascript +class KongPlugin { + constructor(config) { + this.config = config + } + async access(kong) { + // ... + } +} +``` + +The phases you can implement custom logic for are as follows, and the expected function +signature is the same for all of them: + +- `certificate` +- `rewrite` +- `access` +- `response` +- `preread` +- `log` + +Similar to Lua plugins, the presence of the `response` handler automatically enables the buffered proxy mode. + +#### 2. PDK functions + +[kong-js-pdk] invokes PDK functions in Kong through network-based IPC (inter-process communication). +So each function returns a Promise +instance; it's convenient to use `async`/`await` keywords in phase handlers for better readability. + +```javascript +class KongPlugin { + constructor(config) { + this.config = config + } + async access(kong) { + let host = await kong.request.getHeader("host") + // do something to host + } +} +``` + +Or consume Promise in a traditional way: + +```javascript +class KongPlugin { + constructor(config) { + this.config = config + } + async access(kong) { + kong.request.getHeader("host") + .then((host) => { + // do something to host + }) + } +} +``` + +#### 3. Plugin dependencies + +When using the plugin server, plugins are allowed to have extra dependencies, as long as the +directory that holds plugin source code also includes a `node_modules` directory. + +Assuming plugins are stored under `/usr/local/kong/js-plugins`, the extra dependencies are +then defined in `/usr/local/kong/js-plugins/package.json`. Developers also need to +run `npm install` under `/usr/local/kong/js-plugins` to install those dependencies locally +into `/usr/local/kong/js-plugins/node_modules`. + +Note in this case, the node version and architecture that runs the plugin server and +the one that runs `npm install` under plugins directory must match. For example, it may break +when you run `npm install` under macOS and mount the working directory into a Linux container. + +### Testing + +[kong-js-pdk] provides a mock framework to test plugin code correctness through `jest`. + +Install `jest` as a development dependency, and add the `test` script in `package.json`: + +``` +npm install jest --save-dev +``` + +The `package.json` has content similar to the following: + + { + "scripts": { + "test": "jest" + }, + "devDependencies": { + "jest": "^26.6.3", + "kong-pdk": "^0.3.2" + } + } + +Run the test through npm with: + +``` +npm test +``` + +**Note**: Check out [this repository](https://github.com/Kong/kong-js-pdk/tree/master/examples) +for examples on how to write test using `jest`. + +## Developing Python plugins + +{{site.base_gateway}} support for the Python language is provided by [kong-python-pdk]. +The library provides a plugin server to provide runtime for Python plugins, and +functions to access {{site.base_gateway}} features of the [PDK][kong-pdk]. + +### Example configuration + +[kong-python-pdk] can be installed using `pip`. To install the plugin server binary and PDK globally, use: + +``` +pip3 install kong-pdk +``` + +Assume the plugins are stored in `/usr/local/kong/python-plugins`: + +``` +pluginserver_names = python +pluginserver_python_socket = /usr/local/kong/python_pluginserver.sock +pluginserver_python_start_cmd = /usr/local/bin/kong-python-pluginserver --plugins-directory /usr/local/kong/python-plugins +pluginserver_python_query_cmd = /usr/local/bin/kong-python-pluginserver --plugins-directory /usr/local/kong/python-plugins --dump-all-plugins +``` + +### Development + +A valid Python plugin implementation has following attributes: + +```python +Schema = ( + { "message": { "type": "string" } }, +) +version = '0.1.0' +priority = 0 +class Plugin(object): + pass +``` + +A class named `Plugin` defines the class that implements this plugin. `Schema` defines the config +schema of plugin, it shares the same syntax as it's a Lua plugin. `version` and `priority` +defines the version number and priority of execution respectively. + +**Note**: Check out [this repository](https://github.com/Kong/kong-python-pdk/tree/master/examples) +for example Python plugins and [API reference](https://kong.github.io/kong-python-pdk/py-modindex.html). + +#### 1. Phase Handlers + +Similarly to {{site.base_gateway}} Lua plugins, you can implement custom logic to be executed at +various points of the request processing lifecycle. For example, to execute +custom Go code in the access phase, define a function named `access`: + +```python +class Plugin(object): + def __init__(self, config): + self.config = config + def access(self, kong): + pass +``` + +The phases you can implement custom logic for are as follows, and the expected function +signature is the same for all of them: + +- `certificate` +- `rewrite` +- `access` +- `response` +- `preread` +- `log` + +Similar to Lua plugins, the presence of the `response` handler automatically enables the buffered proxy mode. + +#### 2. Type hints + +[kong-python-pdk] supports [type hint](https://www.python.org/dev/peps/pep-0484/) in Python 3.x. To use type lint +and autocomplete in IDE, user can annotate the `kong` parameter in phase handler: + +```python +import kong_pdk.pdk.kong as kong +class Plugin(object): + def __init__(self, config): + self.config = config + def access(self, kong: kong.kong): + host, err = kong.request.get_header("host") +``` + +### Embedded server + +Each plugin can be a microservice. To use the embedded server, use the following code: + +```python +if __name__ == "__main__": + from kong_pdk.cli import start_dedicated_server + start_dedicated_server("py-hello", Plugin, version, priority) +``` + +Note the first argument to `start_dedicated_server` defines the plugin name and must +be unique across all languages. + +#### Example configuration + +Two standalone plugins, called `my-plugin` and `other-one`: + +``` +pluginserver_names = my-plugin,other-one +pluginserver_my_plugin_socket = /usr/local/kong/my-plugin.socket +pluginserver_my_plugin_start_cmd = /path/to/my-plugin.py +pluginserver_my_plugin_query_cmd = /path/to/my-plugin.py --dump +pluginserver_other_one_socket = /usr/local/kong/other-one.socket +pluginserver_other_one_start_cmd = /path/to/other-one.py +pluginserver_other_one_query_cmd = /path/to/other-one.py -dump +``` + +Note that the socket and start command settings coincide with +their defaults, so they can be omitted: + +``` +pluginserver_names = my-plugin,other-one +pluginserver_my_plugin_query_cmd = /path/to/my-plugin --dump +pluginserver_other_one_query_cmd = /path/to/other-one --dump +``` + +### Concurrency model + +Python plugin server and embedded server supports multiple concurrency model. By default, +the server starts in multi-threading mode. + +If your workload is IO intensive, consider the gevent model by adding `-g` to pluginserver's +start_cmd. +If your workload is CPU intensive, consider the multi-processing model by adding `-m` to pluginserver's +start_cmd. + + +## Performance for external plugins + +Depending on implementation details, Go plugins are able to use multiple CPU cores +and so perform best on a multi-core system. JavaScript plugins are currently +single-core only and there's no dedicated plugin server support. +Python plugins can use a dedicated plugin server to span workload to +multiple CPU cores as well. + +Unlike Lua plugins where invoking PDK functions are handled in local processes, +calling PDK functions in external plugins implies inter-process communications and so is a +relatively expensive operation. Because of the expense of calling PDK functions in external plugins, the performance of Kong using external plugins is +highly related to the number of IPC (inter-process communication) calls in each request. + +The following graph demonstrates the correlation between performance and count of IPC +calls per request. Numbers of RPS and latency are removed as they are dependent on +hardware and to avoid confusion. + +
    + +
    + +## Use external plugins in container and Kubernetes + +To use plugins requiring external plugin servers, both the plugin servers and the plugins themselves need to be installed inside the {{ site.base_gateway }} container. + +For plugins written in Golang, build external plugins in embedded server mode in a builder container +and copy or mount the binary artifacts into the {{ site.base_gateway }} container. +For plugins written in JavaScript, first install Node and `npm`, then use `npm` to install `kong-pdk`, and finally +copy or mount the plugins source code into the {{ site.base_gateway }} container. +For plugins written in Python, install Python and `pip`. Then use `pip` to install `kong-pdk`. Finally, +copy or mount the plugin's source code into the {{ site.base_gateway }} container. + +Refer to previous sections on how to configure {{ site.base_gateway }} after you build the image +or create the container. + +{:.note} +> **Note:** Official {{ site.base_gateway }} images are configured to run as the `nobody` user. When building a custom image, to copy files into +the {{ site.base_gateway }} image, you must temporarily set the user to `root`. + +```dockerfile +FROM kong +USER root +# Example for GO: +COPY your-go-plugin /usr/local/bin/your-go-plugin +# Example for JavaScript: +RUN apk update && apk add nodejs npm && npm install -g kong-pdk +COPY you-js-plugin /path/to/your/js-plugins/you-js-plugin +# Example for Python +# PYTHONWARNINGS=ignore is needed to build gevent on Python 3.9 +RUN apk update && \ + apk add python3 py3-pip python3-dev musl-dev libffi-dev gcc g++ file make && \ + PYTHONWARNINGS=ignore pip3 install kong-pdk +COPY you-py-plugin /path/to/your/py-plugins/you-py-plugin +# reset back the defaults +USER kong +ENTRYPOINT ["/docker-entrypoint.sh"] +EXPOSE 8000 8443 8001 8444 +STOPSIGNAL SIGQUIT +HEALTHCHECK --interval=10s --timeout=10s --retries=10 CMD kong health +CMD ["kong", "docker-start"] +``` +--- + +[go-pluginserver]: https://github.com/Kong/go-pluginserver +[go-pluginserver-makefile]: https://github.com/Kong/go-pluginserver/blob/master/Makefile +[go-plugins]: https://github.com/Kong/go-plugins +[go-pdk]: https://github.com/Kong/go-pdk +[kong-pdk]: /gateway/latest/plugin-development/ +[go-hello]: https://github.com/Kong/go-plugins/blob/master/go-hello.go +[kong-js-pdk]: https://github.com/Kong/kong-js-pdk +[kong-python-pdk]: https://github.com/Kong/kong-python-pdk diff --git a/app/gateway/2.7.x/reference/health-checks-circuit-breakers.md b/app/gateway/2.7.x/reference/health-checks-circuit-breakers.md new file mode 100644 index 000000000000..162d0626dd20 --- /dev/null +++ b/app/gateway/2.7.x/reference/health-checks-circuit-breakers.md @@ -0,0 +1,351 @@ +--- +title: Health Checks and Circuit Breakers Reference +--- + +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, +marking them as healthy or unhealthy based on 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 to requests. + +## Defining 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 + } + }, + "threshold": 0 + }, + "slots": 10 +} +``` + +If an upstream is unhealthy (the available capacity % is less than the configured +threshold), 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 load balancer, 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.* + +### Upstreams + +Along with health check functionality on individual targets, Upstreams also +have a notion of health. The health of an Upstream is determined based on the +status of its Targets. + +Configuration of the Upstream's health is done though the property +`healthchecks.threshold`. This is a percentage of minimum available target +"weight" (capacity) for the Upstream to be considered healthy. + +Here is a simple example: + +- Assume an Upstream configured with `healthchecks.threshold=55`. +- It has 5 targets, each with `weight=100`, so the total weight in the ring-balancer is 500. + +When failures start to occur, the circuit-breaker for the first target trips. +It is now considered unhealthy. This means that in the ring-balancer, 20% of +the capacity is now unhealthy (100 weight out of 500). This is still above the +threshold of 55, so the remaining targets will serve the traffic of the failed +one. + +When a second failure occurs, another target fails, and another 100 weight is lost +as unhealthy. Now the ring-balancer operates at 60% of its capacity, but still +within the configured threshold. + +If we assume that the two failures occurred due to a system overload, we can now assume +that the remaining 60% will also not be able to cope with the full load and soon a third +node will fail, reducing healthy capacity to 40%. At this point, the Upstream health +will be less than its threshold, and it will be marked as unhealthy itself. + +Once it enters an unhealthy state, the Upstream will only return errors. This lets the +targets/services recover from the cascading failure they were experiencing. + +Once the Targets start recovering and the Upstream's available capacity passes the +threshold again, the health status of the ring-balancer will automatically be updated. + +## 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} +> **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`. + +### 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. + +## 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][upstreamobject] 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. + +[ringbalancer]: /gateway/{{page.release}}/reference/loadbalancing#ring-balancer +[ringtarget]: /gateway/{{page.release}}/reference/loadbalancing#target +[upstream]: /gateway/{{page.release}}/reference/loadbalancing#upstream +[targetobject]: /gateway/{{page.release}}/admin-api#target-object +[addupstream]: /gateway/{{page.release}}/admin-api#add-upstream +[clustering]: /gateway/{{page.release}}/reference/clustering +[upstreamobject]: /gateway/{{page.release}}/admin-api#upstream-object +[balancercaveats]: /gateway/{{page.release}}/reference/loadbalancing#balancing-caveats +[dnscaveats]: /gateway/{{page.release}}/reference/loadbalancing#dns-caveats diff --git a/app/gateway/2.7.x/reference/loadbalancing.md b/app/gateway/2.7.x/reference/loadbalancing.md new file mode 100644 index 000000000000..be36d9cfd71b --- /dev/null +++ b/app/gateway/2.7.x/reference/loadbalancing.md @@ -0,0 +1,348 @@ +--- +title: Load Balancing Reference +--- + +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 load balancing + +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 hosts file. + +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. + +### 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. + +### 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`. + +### 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]. + +### 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. + +- DNS is carried over UDP with a default limit of 512 Bytes. If there are many entries +to be returned, a DNS Server will respond with partial data and set a truncate flag, +indicating there are more entries unsent. +DNS clients, including Kong's, will then make a second request over TCP to retrieve the full +list of entries. + +- Some nameservers by default do not respond with the truncate flag, but trim the response +to be under 512 byte UDP size. + - Consul is an example. Consul, in its default configuration, returns up to the first +three entries only, and does not set the truncate flag to indicate there are remaining entries unsent. +Consul includes an option to enable the truncate flag. Please refer to [Consul documentation](https://www.consul.io/docs/agent/options.html#enable_truncate) +for more information. + +- If a deployed nameserver does not provide the truncate flag, the pool +of upstream instances might be loaded inconsistently. 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 keep all upstream services in use. + +- 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. + +## 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, for example, "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`. + +### 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' +(which can be overwritten before proxying, using `upstream`'s property +`host_header`) will be load balanced over the targets. A ring-balancer has a +maximum predefined 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. + +Within the balancer there are the positions (from 1 up to the value defined in the `slots` attribute), +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`, while +also having cheap operations when inserting/deleting targets. + +Detailed information on adding and manipulating +upstreams is available in the `upstream` section of the +[Admin API reference][upstream-object-reference]. + +### Target + +A target is an ip address/hostname with a port that identifies an instance of +a backend service. Each upstream can have many targets. +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. + +### Balancing algorithms + +The ring-balancer supports the following load balancing algorithms: `round-robin`, +`consistent-hashing`, and `least-connections`. By default, a ring-balancer +uses the `round-robin` algorithm, which provides a well-distributed weighted +round-robin over the targets. + +When using the `consistent-hashing` algorithm, the input for the hash can be either +`none`, `consumer`, `ip`, `header`, or `cookie`. When set to `none`, the +`round-robin` scheme will be used, and hashing will be disabled. The `consistent-hashing` +algorithm supports a primary and a fallback hashing attribute; in case the primary +fails (e.g., if the primary is set to `consumer`, but no Consumer is authenticated), +the fallback attribute is used. + +Supported hashing attributes are: + +- `none`: Do not use `consistent-hashing`; use `round-robin` instead (default). +- `consumer`: Use the Consumer ID as the hash input. If no Consumer ID is available, + it will fall back on the Credential ID (for example, in case of an external authentication mechanism like LDAP). +- `ip`: Use the originating IP address as the hash input. Review the configuration + settings for [determining the real IP][real-ip-config] when using this. +- `header`: Use a specified header as the hash input. The header name is + specified in either `hash_on_header` or `hash_fallback_header`, depending on whether + `header` is a primary or fallback attribute, respectively. +- `cookie`: Use a specified cookie with a specified path as the hash input. + The cookie name is specified in the `hash_on_cookie` field and the path is + specified in the `hash_on_cookie_path` field. If the specified 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 `consistent-hashing` algorithm is based on _Consistent Hashing_ (or the +_Ketama Principle_), which ensures that when the balancer gets modified by +a change in its targets (adding, removing, failing, or changing weights), only +the minimum number of hashing losses occur. This maximizes upstream cache hits. + +The ring-balancer also supports the `least-connections` algorithm, which selects +the target with the lowest number of connections, weighted by the Target's +`weight` attribute. + +For more information on the exact settings see the `upstream` section of the +[Admin API reference][upstream-object-reference]. + +### 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 (for example, 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`. + +# 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://localhost:8001/upstreams \ + --data "name=address.v1.service" + +# add two targets to the upstream +$ curl -X POST http://localhost:8001/upstreams/address.v1.service/targets \ + --data "target=192.168.34.15:80" + --data "weight=100" +$ curl -X POST http://localhost: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://localhost: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://localhost: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://localhost:8001/upstreams \ + --data "name=address.v2.service" + +# add targets to the upstream +$ curl -X POST http://localhost:8001/upstreams/address.v2.service/targets \ + --data "target=192.168.34.17:80" + --data "weight=100" +$ curl -X POST http://localhost: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://localhost: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. + +# 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://localhost:8001/upstreams/address.v2.service/targets \ + --data "target=192.168.34.17:80" + --data "weight=1000" + +# second target at 0 +$ curl -X POST http://localhost: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://localhost:8001/upstreams/address.v2.service/targets \ + --data "target=192.168.34.17:80" + --data "weight=900" + +# second target at 100 +$ curl -X POST http://localhost: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. + +[upstream-object-reference]: /gateway/{{page.release}}/admin-api#upstream-object +[target-object-reference]: /gateway/{{page.release}}/admin-api#target-object +[dns-order-config]: /gateway/{{page.release}}/reference/configuration/#dns_order +[real-ip-config]: /gateway/{{page.release}}/reference/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/gateway/2.7.x/reference/proxy.md b/app/gateway/2.7.x/reference/proxy.md new file mode 100644 index 000000000000..dc0e4b952e47 --- /dev/null +++ b/app/gateway/2.7.x/reference/proxy.md @@ -0,0 +1,1401 @@ +--- +title: Proxy Reference +--- + +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 the following configuration +properties: + +- `proxy_listen`, which defines a list of addresses/ports on which Kong will + accept **public HTTP (gRPC, WebSocket, etc) 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). +{% include_cached /md/admin-listen.md release=page.release desc='short' %} +- `stream_listen`, which is similar to `proxy_listen` but for Layer 4 (TCP, TLS) + generic proxy. This is turned off by default. + +## 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/connections 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. + +## Overview + +From a high-level perspective, Kong listens for HTTP traffic on its configured +proxy port(s) (`8000` and `8443` by default) and L4 traffic on explicitly configured +`stream_listen` ports. Kong will evaluate any incoming +HTTP request or L4 connection 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 may be 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. Routes have +special attributes that are used for routing - matching incoming HTTP requests. +Routing attributes differ by subsystem (HTTP/HTTPS, gRPC/gRPCS, and TCP/TLS). + +Subsystems and routing attributes: +- `http`: `methods`, `hosts`, `headers`, `paths` (and `snis`, if `https`) +- `tcp`: `sources`, `destinations` (and `snis`, if `tls`) +- `grpc`: `hosts`, `headers`, `paths` (and `snis`, if `grpcs`) + +If one attempts to configure a Route with a routing attribute it doesn't support +(e.g., an `http` route with `sources` or `destinations` fields), an error message +will be reported: + +``` +HTTP/1.1 400 Bad Request +Content-Type: application/json +Server: kong/ + +{ + "code": 2, + "fields": { + "sources": "cannot set 'sources' when 'protocols' is 'http' or 'https'" + }, + "message": "schema violation (sources: cannot set 'sources' when 'protocols' is 'http' or 'https')", + "name": "schema violation" +} +``` + +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" +} +``` + +## 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 entry point 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. + +## Routes and matching capabilities + +Let's now discuss how Kong matches a request against the configured routing +attributes. + +Kong supports native proxying of HTTP/HTTPS, TCP/TLS, and GRPC/GRPCS protocols; +as mentioned earlier, each of these protocols accept a different set of routing +attributes: +- `http`: `methods`, `hosts`, `headers`, `paths` (and `snis`, if `https`) +- `tcp`: `sources`, `destinations` (and `snis`, if `tls`) +- `grpc`: `hosts`, `headers`, `paths` (and `snis`, if `grpcs`) + +Note that all of these fields are **optional**, but at least **one of them** +must be specified. + +For a request to match a Route: + +- The request **must** include **all** of the configured fields +- The values of the fields in the request **must** match at least one of the + configured values (While the field configurations 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 routing properties work together, let's explore +each property individually. + +### Request header + +Kong supports routing by arbitrary HTTP headers. A special case of this +feature is routing by the Host header. + +Routing a request based on its Host header is the most straightforward way to +proxy traffic through 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, and is represented 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 +``` + +Similarly, any other header can be used for routing: + +``` +$ curl -i -X POST http://localhost:8001/routes/ \ + -d 'headers.region=north' +HTTP/1.1 201 Created +``` + +Incoming requests containing a `Region` header set to `North` will be routed to +said Route. + +``` +Region: North +``` + +#### 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 +``` + +#### 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 +``` + +### Additional request headers + +It's possible to route requests by other headers besides `Host`. + +To do this, use the `headers` property in your Route: + +```json +{ + "headers": { "version": ["v1", "v2"] }, + "service": { + "id": "..." + } +} +``` + +Given a request with a header such as: + +```http +GET / HTTP/1.1 +version: v1 +``` + +This request will be routed through to the Service. The same will happen with this one: + +```http +GET / HTTP/1.1 +version: v2 +``` + +But this request will not be routed to the Service: + +```http +GET / HTTP/1.1 +version: v3 +``` + +**Note**: The `headers` keys are a logical `AND` and their values a logical `OR`. + +### Request path + +Another way for a Route to be matched is via request paths. To satisfy this +routing condition, a client request's normalized path **must** be prefixed with one of the +values of the `paths` attribute. + +For example, with a Route configured like so: + +```json +{ + "paths": ["/service", "/hello/world"] +} +``` + +The following requests would be matched: + +```http +GET /service HTTP/1.1 +Host: example.com +``` + +```http +GET /service/resource?param=value HTTP/1.1 +Host: example.com +``` + +```http +GET /hello/world/resource HTTP/1.1 +Host: anything.com +``` + +For each of these requests, Kong detects that their normalized 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. + +#### Using Regex 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 Regex to a Route at the same time. + +For a path to be considered as Regex, it must fall **outside** of the following regex: + +``` +^[a-zA-Z0-9\.\-_~/%]*$ +``` + +In other words, if a path contains any character that is **not** alphanumerical, dot (`.`), +dash (`-`), underscore (`_`), tilde (`~`), forward-slash (`/`), or percent (`%`), then +it will be considered a Regex path. This determination is done on a per-path basis +and it is allowed to mix plain text and regex paths inside the same `paths` array of the same +Route object. + +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 Regex 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). + +**Note**: Regex matching is in general very fast, but it is possible to +construct expressions that take a very long time to determine that they don't +actually match. This happens when the expression results in a "backtrace +exponential explosion", which means that there's an astronomical number of +tests to be performed before it's conclusive that they're all negative. +If undetected, this could take hours to finish with a single regular expression. +The [PCRE](http://pcre.org/) engine automatically detects most types of this +and replaces with more direct approaches, but there are more complex expressions +that could result in this scenario. + +To limit the worst-case scenario, Kong applies the OpenResty +[`lua_regex_match_limit`](https://github.com/openresty/lua-nginx-module#lua_regex_match_limit) +to ensure that any regex operation terminates in around two seconds in the +worst case. Apart from that, a smaller limit is applied to some "critical" +regex operations, like those for path selection, in order to terminate them +within two milliseconds, at most. + +##### Evaluation order + +As previously mentioned, Kong evaluates prefix paths by length, the longest +prefix paths are evaluated first. However, Kong will evaluate Regex paths based +on the `regex_priority` attribute of Routes from highest priority to lowest. +Regex paths are furthermore evaluated before prefix paths. + +Consider the following Routes: + +```json +[ + { + "paths": ["/status/\d+"], + "regex_priority": 0 + }, + { + "paths": ["/version/\d+/status/\d+"], + "regex_priority": 6 + }, + { + "paths": ["/version"], + }, + { + "paths": ["/version/any/"], + } +] +``` + +In this scenario, Kong will evaluate incoming requests against the following +defined URIs, in this order: + +1. `/version/\d+/status/\d+` +2. `/status/\d+` +3. `/version/any/` +4. `/version` + +Take care to avoid writing Regex rules that are overly broad and may consume +traffic intended for a prefix rule. Adding a rule with the path `/version/.*` to +the ruleset above would likely consume some traffic intended for the `/version` +prefix path. If you see unexpected behavior, sending `Kong-Debug: 1` in your +request headers will indicate the matched Route ID in the response headers for +troubleshooting purposes. + +As usual, a request must still match a Route's `hosts` and `methods` properties +as well, and Kong will traverse your Routes until it finds one that [matches +the most rules](#matching-priorities). + +##### 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 other routing attributes), 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" } +``` + +##### Escaping special characters + +Next, it is worth noting that characters found in Regex 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. + +#### 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: ... +``` + +#### Normalization behavior + +To prevent trivial Route match bypass, the incoming request URI from client +is always normalized according to [RFC 3986](https://tools.ietf.org/html/rfc3986) +before router matching occurs. Specifically, the following normalization techniques are +used for incoming request URIs, which are selected because they generally do not change +semantics of the request URI: + +1. Percent-encoded triplets are converted to uppercase. For example: `/foo%3a` becomes `/foo%3A`. +2. Percent-encoded triplets of unreserved characters are decoded. For example: `/fo%6F` becomes `/foo`. +3. Dot segments are removed as necessary. For example: `/foo/./bar/../baz` becomes `/foo/baz`. +4. Duplicate slashes are merged. For example: `/foo//bar` becomes `/foo/bar`. + +The `paths` attribute of the Route object are also normalized. It is achieved by first determining +if the path is a plain text or regex path. Based on the result, different normalization techniques +are used. + +For plain text Route path: + +Same normalization technique as above is used, that is, methods 1 through 4. + +For regex Route path: + +Only methods 1 and 2 are used. In addition, if the decoded character becomes a regex +meta character, it will be escaped with backslash. + +Kong normalizes any incoming request URI before performing router +matches. As a result, any request URI sent over to the upstream services will also +be in normalized form that preserves the original URI semantics. + +### 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). + +### Request source + +{:.note} +> **Note:** This section only applies to TCP and TLS routes. + +The `sources` routing attribute allows +matching a route by a list of incoming connection IP and/or port sources. + +The following Route allows routing via a list of source IP/ports: + +```json +{ + "protocols": ["tcp", "tls"], + "sources": [{"ip":"10.1.0.0/16", "port":1234}, {"ip":"10.2.2.2"}, {"port":9123}], + "id": "...", +} +``` + +TCP or TLS connections originating from IPs in CIDR range "10.1.0.0/16" or IP +address "10.2.2.2" or Port "9123" would match such Route. + +### Request destination + +{:.note} +> **Note:** This section only applies to TCP and TLS routes. + +The `destinations` attribute, similarly to `sources`, +allows matching a route by a list of incoming connection IP and/or port, but +uses the destination of the TCP/TLS connection as routing attribute. + +### Request SNI + +When using secure protocols (`https`, `grpcs`, or `tls`), a [Server +Name Indication][SNI] can be used as a routing attribute. The following Route +allows routing via SNIs: + +```json +{ + "snis": ["foo.test", "example.com"], + "id": "..." +} +``` + +Incoming requests with a matching hostname set in the TLS connection's SNI +extension would be routed to this Route. As mentioned, SNI routing applies not +only to TLS, but also to other protocols carried over TLS - such as HTTPS and +If multiple SNIs are specified in the Route, any of them can match with the incoming request's SNI. +with the incoming request (OR relationship between the names). + +The SNI is indicated at TLS handshake time and cannot be modified after the TLS connection has +been established. This means, for example, that multiple requests reusing the same keepalive connection +will have the same SNI hostname while performing router match, regardless of the `Host` header. +has been established. This means keepalive connections that send multiple requests +will have the same SNI hostnames while performing router match +(regardless of the `Host` header). + +Please note that creating a route with mismatched SNI and `Host` header matcher +is possible, but generally discouraged. + +## Matching priorities + +A Route may define matching rules based on its `headers`, `hosts`, `paths`, and +`methods` (plus `snis` for secure routes - `"https"`, `"grpcs"`, `"tls"`) +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. + +If the rule count for the given request is the same in two Routes `A` and +`B`, then the following tiebreaker rules will be applied in the order they +are listed. Route `A` will be selected over `B` if: + +* `A` has only "plain" Host headers and `B` has one or more "wildcard" + host headers +* `A` has more non-Host headers than `B`. +* `A` has at least one "regex" paths and `B` has only "plain" paths. +* `A`'s longest path is longer than `B`'s longest path. +* `A.created_at < B.created_at` + +## 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. + +### 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]. + +### 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]. + +### 3. Proxying and 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: + +- `connect_timeout`: defines in milliseconds the timeout for + establishing a connection to your upstream service. Defaults to `60000`. +- `write_timeout`: defines in milliseconds a timeout between two + successive write operations for transmitting a request to your upstream + service. Defaults to `60000`. +- `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. +- `X-Forwarded-Prefix: `, where `` is the path of the request which + was accepted by Kong. 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 `$request_uri` variable (with + the query string stripped) provided by [`ngx_http_core_module`][ngx-server-port-variable] + will be used. + + {:.note} + > **Note**: Kong returns `"/"` for an empty path, but it doesn't do any other + > normalization on the request path. + +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. + +### 4. Errors and 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. + +### 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]. + +## 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](#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. + +## Configuring TLS for a Route + +Kong provides a way to dynamically serve TLS certificates on a per-connection +basis. TLS 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. + +TLS 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 a TLS certificate on a given Route: first, upload +your TLS 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=*.tls-example.com,other-tls-example.com" +HTTP/1.1 201 Created +... +``` + +The `snis` form parameter is a convenience parameter. Under the hood, it directly inserts an SNI and +associates the uploaded certificate to it. + +Note that one of the SNI names defined in `snis` above contains a wildcard +(`*.tls-example.com`). An SNI may contain a single wildcard in the leftmost (prefix) or +rightmost (suffix) position. This can be useful when maintaining multiple subdomains. A +single `sni` configured with a wildcard name can be used to match multiple +subdomains, instead of creating an SNI for each. + +Valid wildcard positions are `mydomain.*`, `*.mydomain.com`, and `*.www.mydomain.com`. + +A default certificate can be added using the following parameters in Kong configuration: +1. [`ssl_cert`](/gateway/{{page.release}}/reference/configuration/#ssl_cert) +2. [`ssl_cert_key`](/gateway/{{page.release}}/reference/configuration/#ssl_cert_key) + +Or, by dynamically configuring the default certificate with an SNI of `*`: + +```bash +$ curl -i -X POST http://localhost:8001/certificates \ + -F "cert=@/path/to/default-cert.pem" \ + -F "key=@/path/to/default-cert.key" \ + -F "snis=*" +HTTP/1.1 201 Created +... +``` + +Matching of `snis` respects the following priority: + + 1. Exact SNI matching certificate + 2. Search for a certificate by prefix wildcard + 3. Search for a certificate by suffix wildcard + 4. Search for a certificate associated with the SNI `*` + 5. The default certificate on the file system + +You must now register the following Route within Kong. We will match requests +to this Route using only the Host header for convenience: + +```bash +$ curl -i -X POST http://localhost:8001/routes \ + -d 'hosts=prefix.tls-example.com,other-tls-example.com' \ + -d 'service.id=d54da06c-d69f-4910-8896-915c63c270cd' +HTTP/1.1 201 Created +... +``` + +You can now expect the Route to be served over HTTPS by Kong: + +```bash +$ curl -i https://localhost:8443/ \ + -H "Host: prefix.tls-example.com" +HTTP/1.1 200 OK +... +``` + +When establishing the connection and negotiating the TLS handshake, if your +client sends `prefix.tls-example.com` as part of the SNI extension, Kong will serve +the `cert.pem` certificate previously configured. This is the same for both HTTPS and +TLS connections. + +### Restricting the client protocol + +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"`, `"grpc"`, `"grpcs"`, `"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_ TLS termination previously +occurred from a trusted IP. TLS 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 TLS 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"} +``` + +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": "..." + } +} + +``` + +For L4 TLS proxy to work, it is necessary to create route that accepts +the `tls` `protocol`, as well as having the appropriate TLS certificate +uploaded and their `sni` attribute properly set to match incoming connection's +SNI. Please refer to the [Configuring TLS for a Route](#configuring-tls-for-a-route) +section above for instructions on setting this up. + +## 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. + +### 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 TLS, you can accept `wss` only from the +client, but proxy to the upstream service over plain text, or `ws`. + +## Proxy gRPC traffic + +gRPC proxying is natively supported in Kong. In order +to manage gRPC services and proxy gRPC requests with Kong, create Services and +Routes for your gRPC Services (check out the [Configuring a gRPC Service guide][conf-grpc-service]). + +Only observability and logging plugins are supported with +gRPC - plugins known to be supported with gRPC have "grpc" and "grpcs" listed +under the supported protocols field in their Kong Hub page - for example, +check out the [File Log][file-log] plugin's page. + +## Proxy TCP/TLS traffic + +TCP and TLS proxying is natively supported in Kong. + +In this mode, data of incoming connections reaching the `stream_listen` endpoints will +be passed through to the upstream. It is possible to terminate TLS connections +from clients using this mode as well. + +To use this mode, aside from defining `stream_listen`, appropriate Route/Service +object with protocol types of `tcp` or `tls` should be created. + +If TLS termination by Kong is desired, the following conditions must be met: + +1. The Kong port where TLS connection connects to must have the `ssl` flag enabled +2. A certificate/key that can be used for TLS termination must be present inside Kong, + as shown in [Configuring TLS for a Route](#configuring-tls-for-a-route) + +Kong will use the connecting client's TLS SNI server name extension to find +the appropriate TLS certificate to use. + +On the Service side, depends on whether connection between Kong and the upstream +service need to be encrypted, `tcp` or `tls` protocol types can be set accordingly. +This means all of the below setup are supported in this mode: + +1. Client <- TLS -> Kong <- TLS -> Upstream +2. Client <- TLS -> Kong <- Cleartext -> Upstream +3. Client <- Cleartext -> Kong <- TLS -> Upstream + +**Note:** In L4 proxy mode, only plugins that has `tcp` or `tls` in the supported +protocol list are supported. This list can be found in their respective documentation +on the [Kong Plugin Hub](/hub/). + +[Back to top](#introduction) + +## Proxy TLS passthrough traffic + +{{site.base_gateway}} supports proxying a TLS request without terminating or known +as SNI proxy. + +{{site.base_gateway}} uses the connecting +client's TLS SNI extension to find the matching Route and Service and forward the +complete TLS request upstream, without decrypting the incoming TLS traffic. + +In this mode, you need to: +* Create a Route object with the protocol `tls_passthrough`, and the +`snis` field set to one or more SNIs. +* Set the corresponding Service object's protocol to `tcp`. +* Send requests to a port that has the `ssl` flag in its `stream_listen` +directive. + +Separate SNI and Certificate entities aren't required and won't be used. + +Routes are not allowed to match `tls` and `tls_passthrough` protocols at same time. +However, the same SNI is allowed to match `tls` and `tls_passthrough` in different +Routes. + +It's also possible to set Route to `tls_passthrough` and Service to `tls`. In this +mode, the connection to the upstream will be TLS-encrypted twice. + +{:.note} +> **Note:** To run any plugins in this mode, the plugin's `protocols` field must +include `tls_passthrough`. + +[Back to top](#introduction) + +## 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 TLS 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. + + + +[plugin-configuration-object]: /gateway/{{page.release}}/admin-api#plugin-object +[plugin-development-guide]: /gateway/{{page.release}}/plugin-development +[plugin-association-rules]: /gateway/{{page.release}}/admin-api/#precedence +[proxy-websocket]: /gateway/{{page.release}}/reference/proxy/#proxy-websocket-traffic +[load-balancing-reference]: /gateway/{{page.release}}/reference/loadbalancing +[configuration-reference]: /gateway/{{page.release}}/reference/configuration/ +[configuration-trusted-ips]: /gateway/{{page.release}}/reference/configuration/#trusted_ips +[configuring-a-service]: /gateway/{{page.release}}/get-started/quickstart/configuring-a-service +[API]: /gateway/{{page.release}}/admin-api +[service-entity]: /gateway/{{page.release}}/admin-api/#add-service +[route-entity]: /gateway/{{page.release}}/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 +[conf-grpc-service]: /gateway/{{page.release}}/get-started/quickstart/configuring-a-grpc-service +[file-log]: /hub/kong-inc/file-log diff --git a/app/gateway/2.7.x/reference/rate-limiting.md b/app/gateway/2.7.x/reference/rate-limiting.md new file mode 100644 index 000000000000..89366ba81bde --- /dev/null +++ b/app/gateway/2.7.x/reference/rate-limiting.md @@ -0,0 +1,171 @@ +--- +title: Rate Limiting Library +badge: enterprise +--- + +## Overview + + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + + +This library is designed to provide an efficient, scalable, eventually-consistent sliding window rate limiting library. It relies on atomic operations in shared ngx memory zones to track window counters within a given node, periodically syncing this data to a central data store. + +A sliding window rate limiting implementation tracks the number of hits assigned to a specific key (such as an IP address, Consumer, Credential, etc) within a given time window, taking into account previous hit rates to smooth out a calculated rate, while still providing a familiar windowing interface that modern developers are used to (e.g., n hits per second/minute/hour). This is similar to a fixed window implementation, in which request rates reset at the beginning of the window, but without the "reset bump" from which fixed window implementations suffer, while providing a more intuitive interface beyond what leaky bucket or token bucket implementations can offer. Note that we use the term "hit" instead of "request" when referring to incrementing values for rate limit keys, because this library provides an abstract rate limiting interface; a sliding window implementation may have uses outside of HTTP request rate limiting, thus, we describe this library in a more abstract sense. + +A sliding window takes into account a weighted value of the previous window when calculating the current rate for a given key. A window is defined as a period of time, starting at a given "floor" timestamp, where the floor is calculated based on the size of the window. For window sizes of 60 seconds, the floor always falls at the 0th second (e.g., at the beginning of any given minute). Likewise, windows with a size of 30 seconds will begin at the 0th and 30th seconds of each minute. + +Consider a rate limit of 10 hits per minute. In this configuration, this library will calculate the hit rate of a given key based on the number of hits for the current window (starting at the beginning of the current minute), and a weighted percentage of all hits of the previous window (e.g., the previous minute). This weight is calculated based on the current timestamp with respect to the window size in question; the farther away the current time is from the start of the previous window, the lower the weight percentage. This value is best expressed through an example: + +``` +current window rate: 10 +previous window rate: 40 +window size: 60 +window position: 30 (seconds past the start of the current window) +weight = .5 (60 second window size - 30 seconds past the window start) + +rate = 'current rate' + 'previous weight' * 'weight' + = 10 + 40 * ('window size' - 'window position') / 'window size' + = 10 + 40 * (60 - 30) / 60 + = 10 + 40 * .5 + = 30 +``` +Strictly speaking, the formula used to define the weighting percentage is as follows: + +`weight = (window_size - (time() % window_size)) / window_size` + +Where `time()` is the value of the current Unix timestamp. + +Each node in the Kong cluster relies on its own in-memory data store as the source of truth for rate limiting counters. Periodically, each node pushes a counter increment for each key it saw to the cluster, which is expected to atomically apply this diff to the appropriate key. The node then retrieves this key's value from the data store, along with other relevant keys for this data sync cycle. In this manner, each node shares the relevant portions of data with the cluster, while relying on a very high-performance method of tracking data during each request. This cycle of converge -> diverge -> reconverge among nodes in the cluster provides our eventually-consistent model. + +The periodic rate at which nodes converge is configurable; shorter sync intervals will result in less divergence of data points when traffic is spread across multiple nodes in the cluster (e.g., when sitting behind a round robin balancer), whereas longer sync intervals put less r/w pressure on the datastore, and less overhead on each node to calculate diffs and fetch new synced values. The desirable value here depends on use case; when using cluster syncing to refresh nodes periodically (e.g., to inform new cluster nodes of counter data), a value of 10-30 seconds may be desirable, to minimize data store traffic. Contrarily, environments demanding stronger consistency between nodes (such as orchestrated deployments involving a high churn rate among cluster membership, or cases where strict rate limiting policies must be applied to node sitting behind a non-hashing load balancer) should use a lower sync period, on the order of milliseconds. The minimum possible value is 0.001 (1 millisecond), though practically this value is limited by network performance between Kong nodes and the configured data store. + +In addition to periodic data sync behavior, this library can implement rate limiting counter in a synchronous pattern by defining its `sync_rate` as `0`. In such a case, the given counter will be applied directly to the datastore. This behavior is desirable in cases where stronger consistency among the cluster is desired; such a configuration comes with the cost of needing to communicate with the datastore (or Redis) on every request, which can induce noticeable latency into the request ("noticeable" being a relative term of typically a few milliseconds, depending on the performance of the storage mechanism in question; for comparison, Kong typically processes requests on the order of tens of microseconds). + +This library can also forgo syncing counter data entirely, and only apply incremental counters to its local memory zone, by defining a `sync_rate` value of less than `0`. This behavior is useful when cluster-wide syncing of data is unnecessary, such as environments using only a single Kong node, or where Kong nodes live behind a hashing load balancer and are treated as isolated instances. + +Module configuration data, such as sync rate, shared dictionary name, storage policy, etc, is kept in a per-worker public configuration table. Multiple configurations can be defined as stored as arbitrary `namespaces` (more on this below). + +## Developer Notes +### Public Functions +The following public functions are provided by this library: + +`ratelimiting.new` + +Syntax: +``` +ok = ratelimiting.new(opts) +``` + +Define configurations for a new namespace. The following options are accepted: + +- `dict`: Name of the shared dictionary to use +- `sync_rate`: Rate, in seconds, to sync data diffs to the storage server. +- `strategy`: Storage strategy to use. Currently `cassandra`, `postgres`, and `redis` are supported. Strategies must provide several public—functions defined below. +- `strategy_opts`: A table of options used by the storage strategy. Currently only applicable for the `redis` strategy. +- `namespace`: String defining these config values. A namespace may only be defined once; if a namespace has already been defined on this worker, an error is thrown. If no namespace is defined, the literal string "default" will be used. +- `window_sizes`: A list of window sizes used by this configuration. + +`ratelimiting.increment` + +Syntax: +``` +rate = ratelimiting.increment(key, window_size, value, namespace?) +``` + +Increment a given key for `window_size` by value. If namespace is undefined, the "default" namespace is used. value can be any number Lua type (but ensure that the storage strategy in use for this namespace can support decimal values if a non-integer value is provided). This function returns the sliding rate for this key/window size after the increment of value has been applied. + +`ratelimit.sliding_window` + +Syntax: +``` +rate = ratelimit.sliding_window(key, window_size, cur_diff?, namespace?) +``` + +Return the current sliding rate for this key/window size. An optional `cur_diff` value can be provided that overrides the current stored diff for this key. If `namespace` is undefined, the "default" namespace is used. + +`ratelimiting.sync` + +Syntax: +``` +ratelimiting.sync(premature, namespace?) +``` + +Sync all currently stored key diffs in this worker with the storage server, and retrieve the newly synced value. If namespace is undefined, the "default" `namespace` is used. Before the diffs are pushed, another sync call for the given namespace is scheduled at `sync_rate` seconds in the future. Given this, this function should typically be called during the `init_worker` phase to initialize the recurring timer. This function is intended to be called in an `ngx.timer` context; hence, the first variable represents the injected `premature` param. + +`ratelimiting.fetch` + +Syntax: +``` +ratelimiting.fetch(premature, namespace, time, timeout?) +``` + +Retrieve all relevant counters for the given namespace at the given time. This +function establishes a shm mutex such that only one worker will fetch and +populate the shm per execution. If timeout is defined, the mutex will expire +based on the given timeout value; otherwise, the mutex is unlocked immediately +following the dictionary update. This function can be called in an `ngx.timer` +context; hence, the first variable represents the injected `premature` param. + +### Strategy Functions + +Storage strategies must provide the following interfaces: + +#### strategy_class.new + +Syntax: +``` +strategy = strategy_class.new(dao_factory, opts) +``` + +Implement a new strategy object. `opts` is expected to be a table type, and can be used to pass opaque/arbitrary options to the strategy class. + +#### strategy:push_diffs + +Syntax: +``` +strategy:push_diffs(diffs) +``` + +Push a table of key diffs to the storage server. diffs is a table provided in the following format: + +``` +[1] = { + key = "1.2.3.4", + windows = { + { + window = 12345610, + size = 60, + diff = 5, + namespace = foo, + }, + { + window = 12345670, + size = 60, + diff = 5, + namespace = foo, + }, + } + }, + ... + ["1.2.3.4"] = 1, + ... + ``` + +#### strategy:get_counters + +Syntax: +``` +rows = strategy:get_counters(namespace, window_sizes, time?) +``` + +Return an iterator for each key stored in the datastore/redis for a given `namespace` and list of window sizes. 'time' is an optional unix second- precision timestamp; if not provided, this value will be set via `ngx.time()`. It is encouraged to pass this via a previous defined timestamp, depending on the context (e.g., if previous calls in the same thread took a nontrivial amount of time to run). + +#### strategy:get_window + +Syntax: +``` +window = strategy:get_window(key, namespace, window_start, window_size) +``` + +Retrieve a single key from the data store based on the values provided. diff --git a/app/gateway/2.7.x/vitals/index.md b/app/gateway/2.7.x/vitals/index.md new file mode 100644 index 000000000000..a35b54140511 --- /dev/null +++ b/app/gateway/2.7.x/vitals/index.md @@ -0,0 +1,94 @@ +--- +title: Vitals Overview +badge: enterprise +--- + +Use Kong Vitals (Vitals) to monitor {{site.ee_product_name}} health and performance, and to understand the microservice API transactions traversing Kong. Vitals uses visual API analytics to see exactly how your APIs and Gateway are performing. Quickly access key statistics, monitor vital signs, and pinpoint anomalies in real time. + +* Use Kong Admin API to access Vitals data via endpoints. Additional visualizations, including dashboarding of Vitals data alongside data from other systems, can be achieved using the Vitals API to integrate with common monitoring systems. + +* Use Kong Manager to view visualizations of Vitals data, including the Workspaces Overview Dashboard, Workspace Charts, Vitals tab, and Status Codes, and to generate CSV Reports. + +![Vitals Overview](/assets/images/products/gateway/vitals/vitals_overview.png) + +## Prerequisites +Vitals is enabled by default in {{site.ee_product_name}} and available upon the first login of a Super Admin. + + +{% include_cached /md/enterprise/cassandra-deprecation.md %} + + +You will need one of the following databases to use Vitals: +* InfluxDB +* PostgreSQL 9.5+ +* Cassandra 2.1+ + +## Guidelines for viewing Vitals +When using Vitals, note: +* Vitals is enabled by default and accessible the first time a Super Admin logs in. + * To enable or disable Vitals, see [Enable or Disable Vitals](#enable-or-disable-vitals). +* Any authorized user can view Vitals for the entire Kong cluster or for a particular Workspace. + * If a user does not have access to a Workspace, its Vitals are hidden from view. + * If a user does not have access to Vitals data, charts will not display. + +## Vitals API +Vitals data is available via endpoints on Kong’s Admin API. Access to these endpoints may be controlled via Admin API RBAC. The Vitals API is described in the OAS (Open API Spec, formerly Swagger) file. See a sample here (downloadable file): [`vitalsSpec.yaml`](/gateway/{{page.release}}/vitals/vitalsSpec.yaml). + +## Viewing Vitals in Kong Manager +View Vitals information in Kong Manager using any of the following: +* Overview Dashboard, available from the Workspaces page for an overview of your Kong cluster, or an individual Workspace for an overview of the selected Workspace. +* Workspace charts, which display on the Workspaces page beneath the Overview Dashboard. These charts give a quick overview of the status of an individual Workspace. +* Vitals tab, which provides detailed information about your Kong cluster, including total requests, latency, and cache information. +* Status Codes to view cluster-wide status code classes. + +## Overview Dashboard +When you log in to Kong Manager, the Workspaces page displays by default. The top of the page displays the Vitals Overview Dashboard summarizing your Kong cluster, including the health and performance of your APIs and Gateway, total requests, average error rate, total consumers, and total services. This Vitals Overview Dashboard makes it easy for an Admin to quickly identify any issues that need attention. + +## Workspace charts +On the Workspaces page, beneath the Overview Dashboard, the Workspaces section displays each Workspace with a chart showing Vitals for the most recently added services, consumers, and plugins for that Workspace. Hover over a coordinate to view the exact number of successes and errors at a given timestamp, or drilldown into the Workspace chart for more details. + +## Vitals tab +The Vitals tab, or Vitals view, displays metrics about the health and performance of Kong nodes and Kong-proxied APIs. The Vitals View displays total requests, latency, and cache information. You also can generate reports from the Vitals view. + +Options to populate the Vitals view, or areas in the chart, include: + +| Option | Description | +|--------------------------|----------------------------------------------------------------------------------------------| +| Timeframe Selector | A timeframe selector controls the timeframe of data visualized, which indirectly controls the granularity of the data. For example, the “Last 5 Minutes” selection displays 1-second resolution data, while longer time frames display 1-minute resolution data. +| View | Select to populate the Vitals chart by Hostname, Hostname + ID, or ID.| +| Total Requests | The Total Requests chart displays a count of all proxy requests received. This includes requests that were rejected due to rate-limiting, failed authentication, and so on.| +| Cluster and Node Data | Metrics are displayed on Vitals charts at both node and cluster level. Controls are available to show cluster-wide metrics and/or node-specific metrics. Clicking on individual nodes will toggle the display of data from those nodes. Nodes are identified by a unique Kong node identifier, by hostname, or by a combination of the two.| + +## Status Codes +The Status Codes view displays visualizations of cluster-wide status code classes (1xx, 2xx, 3xx, 4xx, 5xx). The Status Codes view contains the counts of status code classes graphed over time, as well as the ratio of code classes to total requests. See [Status Codes](/gateway/{{page.release}}/vitals/vitals-metrics/#status-code). + +>**Note**: The Status Codes view does not include non-standard code classes (6xx, 7xx, etc.). Individual status code data can be viewed in the Consumer, Route, and Service details pages under the Activity tab. Both standard and non-standard status codes are visible in these views. + +## Enable or disable Vitals +{{site.ee_product_name}} ships with Vitals enabled by default. To enable or disable Vitals, edit the configuration file or environment variables. + +{% navtabs %} +{% navtab Using kong.conf %} + +1. Edit the configuration file to enable or disable Vitals: + ```bash + # via your Kong configuration file; e.g., kong.conf + $ vitals = on # vitals is enabled + $ vitals = off # vitals is disabled + ``` +2. Restart Kong. + +{% endnavtab %} +{% navtab Using environment variables %} + +1. Use environment variables to enable or disable Vitals: + ```bash + # or via environment variables + $ export KONG_VITALS=on + $ export KONG_VITALS=off + ``` + +2. Restart Kong. + +{% endnavtab %} +{% endnavtabs %} diff --git a/app/gateway/2.7.x/vitals/vitals-estimates.md b/app/gateway/2.7.x/vitals/vitals-estimates.md new file mode 100644 index 000000000000..96e3a024111c --- /dev/null +++ b/app/gateway/2.7.x/vitals/vitals-estimates.md @@ -0,0 +1,177 @@ +--- +title: Estimate Vitals Storage in PostgreSQL +badge: enterprise +--- + +Vitals data can be divided into two categories: {{site.base_gateway}} node statistics and request response codes. + +## {{site.base_gateway}} node statistics + +These types of metrics are proxy latency, upstream latency, and cache hit/miss. {{site.base_gateway}} node statistics are stored in tables like the following: + +* `vitals_stats_seconds_timestamp` stores 1 new row for every _second_ Kong runs +* `vitals_stats_minutes` stores 1 new row for every _minute_ Kong runs +* `vitals_stats_days` stores 1 new row for every _day_ Kong runs + +{{site.base_gateway}} node statistics are not associated with specific {{site.base_gateway}} entities like Workspaces, Services, or Routes. They're designed to represent the cluster's state in time. This means the tables will have new rows regardless if {{site.base_gateway}} is routing traffic or idle. + +The tables do not grow infinitely and hold data for the following duration of time: + +* `vitals_stats_seconds_timestamp` holds data for 1 hour (3600 rows) +* `vitals_stats_minutes` holds data for 25 hours (90000 rows) +* `vitals_stats_days` holds data for 2 years (730 rows) + +## Request response codes + +Request response codes are stored in the other group of tables following a different rationale. Tables in this group share the same structure (`entity_id`, `at`, `duration`, `status_code`, `count`): + +* `vitals_code_classes_by_workspace` +* `vitals_code_classes_by_cluster` +* `vitals_codes_by_route` + +The `entity_id` does not exist in `vitals_code_classes_by_cluster` as this table doesn't store entity-specific information. +In the `vitals_code_classes_by_workspace` table, `entity_id` is `workspace_id`. In the `vitals_codes_by_route` table, `entity_id` is `service_id` and `route_id`. + +`at` is a timestamp. It logs the start of the period a row represents, while `duration` is the duration of that period. + +`status_code` and `count` are the quantity of the HTTP status codes (200, 300, 400, 500) observed in the period represented by a row. + +While {{site.base_gateway}} node statistic tables grow only according to time, status code tables only have new rows when {{site.base_gateway}} proxies traffic, and the number of new rows depends on the traffic itself. + +## Example + +Consider a brand new {{site.base_gateway}} that hasn't proxied any traffic yet. {{site.base_gateway}} node statistic tables have rows but status codes tables don't. + +When {{site.base_gateway}} proxies its first request at `t` returning status code 200, the following rows are added: + +```bash +vitals_codes_by_cluster +[second(t), 1, 200, 1] +[minute(t), 60, 200, 1] +[day(t), 84600, 200, 1] +``` + +Second, minute, and day content is trimmed in the following way: + +* `second(t)` is `t` trimmed to seconds, for example: `second(2021-01-01 20:21:30)` would be `2021-01-01 20:21:30`. +* `minute(t)` is `t` trimmed to minutes, for example: `minute(2021-01-01 20:21:30.234)` would be `2021-01-01 20:21:00`. +* `day(t)` is `t` trimmed to day, for example: `day(2021-01-01 20:21:30.234)` would be `2021-01-01 00:00:00`. + +```bash +vitals_codes_by_workspace +[workspace_id, second(t), 1, 200, 1] +[workspace_id, minute(t), 60, 200, 1] +[workspace_id, day(t), 84600, 200, 1] + +vitals_codes_by_route +[service_id, route_id, second(t), 1, 200, 1] +[service_id, route_id, minute(t), 60, 200, 1] +[service_id, route_id, day(t), 84600, 200, 1] +``` + +Let's consider what happens when new requests are proxied in some scenarios. + +### Scenario where no rows are inserted + +If we make the same request again at the same `t` and it also receives 200, no new rows will be inserted. + +In this case, the existing rows have their count column incremented accordingly: + +```bash +vitals_codes_by_cluster +[second(t), 1, 200, 2] +[minute(t), 60, 200, 2] +[day(t), 84600, 200, 2] + +vitals_codes_by_workspace +[workspace_id, second(t), 1, 200, 2] +[workspace_id, minute(t), 60, 200, 2] +[workspace_id, day(t), 84600, 200, 2] + +vitals_codes_by_route +[service_id, route_id, second(t), 1, 200, 2] +[service_id, route_id, minute(t), 60, 200, 2] +[service_id, route_id, day(t), 84600, 200, 2] +``` + +### Scenario where new rows are inserted + +If the last request received a 500 status code, new rows are inserted: + +```bash +vitals_codes_by_cluster +[second(t), 1, 200, 1] +[minute(t), 60, 200, 1] +[day(t), 84600, 200, 1] + +[second(t), 1, 500, 1] +[minute(t), 60, 500, 1] +[day(t), 84600, 500, 1] + +vitals_codes_by_workspace +[workspace_id, second(t), 1, 200, 1] +[workspace_id, minute(t), 60, 200, 1] +[workspace_id, day(t), 84600, 200, 1] + +[workspace_id, second(t), 1, 500, 1] +[workspace_id, minute(t), 60, 500, 1] +[workspace_id, day(t), 84600, 500, 1] + +vitals_codes_by_route +[service_id, route_id, second(t), 1, 200, 1] +[service_id, route_id, minute(t), 60, 200, 1] +[service_id, route_id, day(t), 84600, 200, 1] + +[service_id, route_id, second(t), 1, 500, 1] +[service_id, route_id, minute(t), 60, 500, 1] +[service_id, route_id, day(t), 84600, 500, 1] +``` + +### Scenario where a second row is inserted + +Assume that at `t + 5s`, where `minute(t)==minute(t + 5s)`, {{site.base_gateway}} proxies the same request returning 200. Since `minute()` and `day()` for both `t` and `t + 5s` are the same, minute and day rows should just be updated. Since `second()` is different for the two instants, a new second row should be inserted in each table. + +```bash +vitals_codes_by_cluster +[second(t), 1, 200, 1] +[second(t + 5s), 1, 200, 1] +[minute(t), 60, 200, 2] +[day(t), 84600, 200, 2] + +vitals_codes_by_workspace +[workspace_id, second(t), 1, 200, 1] +[workspace_id, second(t + 5s), 1, 200, 1] +[workspace_id, minute(t), 60, 200, 2] +[workspace_id, day(t), 84600, 200, 2] + +vitals_codes_by_route +[service_id, route_id, second(t), 1, 200, 1] +[service_id, route_id, second(t + 5s), 1, 200, 1] +[service_id, route_id, minute(t), 60, 200, 2] +[service_id, route_id, day(t), 84600, 200, 2] +``` + +In summary, the number of rows in those status codes tables is directly related to: + +* The number of status codes observed in {{site.base_gateway}} proxied requests +* The number of {{site.base_gateway}} entities involved in those requests +* The constant flow of proxied requests + +In an estimate of row numbers in scenario, consider a {{site.base_gateway}} cluster with the following characteristics: + +* A constant flow of requests returning all 5 possible groups of status codes (1xx, 2xx, 3xx, 4xx and 5xx). +* Just 1 workspace, 1 service, and 1 route + +After 24 hours of traffic, the status codes tables will have this number of rows: + +Status code table name | Day | Minute | Seconds | Total +---------------------- | --- | ------ | ------- | ----- +`vitals_codes_by_cluster` | 5 | 7200 | 18000 | 25200 +`vitals_codes_by_workspace` | 5 | 7200 | 18000 | 25200 +`vitals_codes_by_route` | 5 | 7200 | 18000 | 25200 + +It's important to note that this assumes that all 5 groups of status codes had been observed in those 24 hours of traffic. This is why quantities were multiplied by 5. + +With this baseline scenario, it's easier to calculate what happens when the number of {{site.base_gateway}} entities (Workspaces and Routes) involved in the traffic increases. Tables `vitals_codes_by_workspace` and `vitals_codes_by_route` have their row number change with increase in workspaces and routes, respectively. + +If the above {{site.base_gateway}} cluster is expanded to have 10 workspaces with 1 route each (10 routes total) and it proxies traffic for 24 hours and returns all 5 status codes, `vitals_codes_by_workspace` and `vitals_codes_by_route` would have 252,000 rows. diff --git a/app/gateway/2.7.x/vitals/vitals-influx-strategy.md b/app/gateway/2.7.x/vitals/vitals-influx-strategy.md new file mode 100644 index 000000000000..35c06c690644 --- /dev/null +++ b/app/gateway/2.7.x/vitals/vitals-influx-strategy.md @@ -0,0 +1,284 @@ +--- +title: Vitals with InfluxDB +badge: enterprise +--- + +Leveraging a time series database for Vitals data +can improve request and Vitals performance in very-high traffic {{site.ee_product_name}} +clusters (such as environments handling tens or hundreds of thousands of +requests per second), without placing additional write load on the database +backing the Kong cluster. + +For information about using Kong Vitals with a database as the backend, refer to +[Kong Vitals](/gateway/{{page.release}}/vitals/). + +## Set up Kong Vitals with InfluxDB + +### Install {{site.base_gateway}} + +If you already have a {{site.base_gateway}} instance, skip to [deploying a license](#deploy-a-kong-gateway-license). + +If you have not installed {{site.base_gateway}}, a Docker installation +will work for the purposes of this guide. + + +### Pull the {{site.base_gateway}} Docker image {#pull-image} + +1. Pull the following Docker image. + + ```bash + docker pull kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine + ``` + + {:.important} + > Some [older {{site.base_gateway}} images](https://support.konghq.com/support/s/article/Downloading-older-Kong-versions) + are not publicly accessible. If you need a specific patch version and can't + find it on [Kong's public Docker Hub page](https://hub.docker.com/r/kong/kong-gateway), contact + [Kong Support](https://support.konghq.com/). + + You should now have your {{site.base_gateway}} image locally. + +1. Tag the image. + + ```bash + docker tag kong/kong-gateway:{{page.releases_hash[page.version-index].ee-version}}-alpine kong-ee + ``` + + +### Start the database and {{site.base_gateway}} containers + +1. Create a custom network to allow the containers to discover and communicate +with each other. + + ```bash + docker network create kong-ee-net + ``` + +1. Start a PostgreSQL container: + + ```p + docker run -d --name kong-ee-database \ + --network=kong-ee-net \ + -p 5432:5432 \ + -e "POSTGRES_USER=kong" \ + -e "POSTGRES_DB=kong" \ + -e "POSTGRES_PASSWORD=kong" \ + postgres:9.6 + ``` + +1. Prepare the Kong database: + + ```sh + docker run --rm --network=kong-ee-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=kong" \ + -e "KONG_PASSWORD=kongpass" \ + kong-ee kong migrations bootstrap + ``` + +1. Start the gateway with Kong Manager: + +{% include_cached /md/admin-listen.md release=page.release desc='long' %} + + ```sh + docker run -d --name kong-ee --network=kong-ee-net \ + -e "KONG_DATABASE=postgres" \ + -e "KONG_PG_HOST=kong-ee-database" \ + -e "KONG_PG_PASSWORD=kong" \ + -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \ + -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \ + -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \ + -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \ + -e "KONG_ADMIN_GUI_URL=http://localhost:8002" \ + -e "KONG_VITALS_STRATEGY=influxdb" \ + -e "KONG_VITALS_TSDB_ADDRESS=influxdb:8086" \ + -p 8000:8000 \ + -p 8443:8443 \ + -p 8001:8001 \ + -p 8444:8444 \ + -p 8002:8002 \ + -p 8445:8445 \ + -p 8003:8003 \ + -p 8004:8004 \ + kong-ee + ``` + + {:.note} + > **Note:** For `KONG_ADMIN_GUI_URL`, replace `localhost` + with with the DNS name or IP of the Docker host. `KONG_ADMIN_GUI_URL` + _should_ have a protocol, for example, `http://`. + +### Deploy a {{site.base_gateway}} license + +If you already have a {{site.ee_product_name}} license attached to your {{site.base_gateway}} +instance, skip to [starting an InfluxDB database](#start-an-influxdb-database). + +You will not be able to access the Kong Vitals functionality without a valid +{{site.ee_product_name}} license attached to your {{site.base_gateway}} instance. + +{% include_cached /md/enterprise/deploy-license.md heading="####" release=page.release %} + +### Start an InfluxDB database + +Production-ready InfluxDB installations should be deployed as a separate +effort, but for proof-of-concept testing, running a local InfluxDB instance +is possible with Docker: + +```bash +$ docker run -p 8086:8086 \ + --network= \ + --name influxdb \ + -e INFLUXDB_DB=kong \ + influxdb:1.8.4-alpine +``` + +{:.warning} +> You **must** use InfluxDB 1.8.4-alpine because +InfluxDB 2.0 will **not** work. + +Writing Vitals data to InfluxDB requires that the `kong` database is created, +this is done using the `INFLUXDB_DB` variable. + +### Configure {{site.base_gateway}} + +{:.note} +> **Note:** If you used the configuration in +[Installing {{site.base_gateway}} on Docker](#install-kong-gateway), +then you do not need to complete this step. + +In addition to enabling Kong Vitals, {{site.base_gateway}} must be configured to use InfluxDB as the +backing strategy for Vitals. The InfluxDB host and port must also be defined: + +```bash +$ echo "KONG_VITALS_STRATEGY=influxdb KONG_VITALS_TSDB_ADDRESS=influxdb:8086 kong reload exit" \ +| docker exec -i kong-ee /bin/sh +``` + +{:.note} +> **Note**: In Hybrid Mode, configure [`vitals_strategy`](/gateway/{{page.release}}/reference/configuration/#vitals_strategy) +and [`vitals_tsdb_address`](/gateway/{{page.release}}/reference/configuration/#vitals_tsdb_address) +on both the control plane and all data planes. + +## Understanding Vitals data using InfluxDB measurements + +Kong Vitals records metrics in two InfluxDB measurements: + +1. `kong_request`: Contains field values for request latencies and HTTP, + and tags for various Kong entities associated with the requests (for + example, the Route and Service in question). +2. `kong_datastore_cache`: Contains points about cache hits and + misses. + +To display the measurement schemas on your InfluxDB instance running +in Docker: + +1. Open command line in your InfluxDB Docker container. + + ```sh + $ docker exec -it influxdb /bin/sh + ``` + +2. Log in to the InfluxDB CLI. + + ```sh + $ influx -precision rfc3339 + ``` + +3. Enter the InfluxQL query for returning a list of tag keys associated +with the specified database. + + ```sql + > SHOW TAG KEYS ON kong + ``` + + Example result: + + ```sql + name: kong_request + tagKey + ------ + consumer + hostname + route + service + status_f + wid + workspace + + name: kong_datastore_cache + tagKey + ------ + hostname + wid + ``` + +4. Enter the InfluxQL query for returning the field keys and the +data type of their field values. + + ```sh + > SHOW FIELD KEYS ON kong + ``` + + Example result: + + ```sql + name: kong_request + fieldKey fieldType + -------- --------- + kong_latency integer + proxy_latency integer + request_latency integer + status integer + + name: kong_datastore_cache + fieldKey fieldType + -------- --------- + + hits integer + misses integer + ``` + +The tag `wid` is used to differentiate the unique worker ID per host, to avoid +duplicate metrics shipped at the same point in time. + +As demonstrated above, the series cardinality of the `kong_request` measurement +varies based on the cardinality of the Kong cluster configuration - a greater +number of Service/Route/Consumer/Workspace combinations handled by Kong results +in a greater series cardinality as written by Vitals. + +## Sizing an InfluxDB node/cluster for Vitals + +Consult the +[InfluxDB sizing guidelines](https://docs.influxdata.com/influxdb/v1.8/guides/hardware_sizing/) +for reference on appropriately sizing an InfluxDB node/cluster. + +{:.note} +> **Note:** The query behavior when reading Vitals data falls under the "moderate" load +category as defined by the InfluxDB sizing guidelines. Several `GROUP BY` statements and +functions are used to generate the Vitals API responses, which can require +significant CPU resources to execute when hundreds of thousands or millions of +data points are present. + +## Query frequency and precision + +Kong buffers Vitals metrics and writes InfluxDB points in batches to improve +throughput in InfluxDB and reduce overhead in the Kong proxy path. Each Kong +worker process flushes its buffer of metrics every 5 seconds or 5000 data points, +whichever comes first. + +Metrics points are written with microsecond (`u`) precision. To comply with +the [Vitals API](/gateway/{{page.release}}/vitals/vitalsSpec.yaml), measurement +values are read back grouped by second. + +{:.note} +> **Note:** Because of limitations in the OpenResty API, writing values with +microsecond precision requires an additional syscall per request. + +## Managing the retention policy of the Kong database + +Vitals InfluxDB data points are not downsampled or managed by a +retention policy through Kong. InfluxDB operators are encouraged to manually manage +the retention policy of the `kong` database to reduce the disk space and memory +needed to manage Vitals data points. diff --git a/app/gateway/2.7.x/vitals/vitals-metrics.md b/app/gateway/2.7.x/vitals/vitals-metrics.md new file mode 100644 index 000000000000..99edb5dca20a --- /dev/null +++ b/app/gateway/2.7.x/vitals/vitals-metrics.md @@ -0,0 +1,113 @@ +--- +title: Vitals Metrics +badge: enterprise +--- + +Vitals metrics fall into two categories: +* Health Metrics — for monitoring the health of a Kong cluster +* Traffic Metrics — for monitoring the usage of upstream services + + +All metrics are collected at 1-second intervals and aggregated into 1-minute +intervals. The 1-second intervals are retained for one hour. The 1-minute +intervals are retained for 25 hours. + +If longer retention times are needed, the Vitals API can be used to pull metrics +out of Kong and into a data retention tool. + +## Health Metrics + +Health metrics give insight into the performance of a Kong cluster; for example, +how many requests the cluster is processing and the latency on those requests. + +Health metrics are tracked for each node in a cluster as well as for the cluster +as a whole. In Kong, a node is a running process with a unique identifier, +configuration, cache layout, and connections to both Kong’s datastores and the +upstream APIs it proxies. Note that node identifiers are unique to the process, +and not to the host on which the process runs. In other words, each Kong restart +results in a new node, and therefore a new node ID. + +### Latency + +The Vitals API may return null for Latency metrics. This occurs when no API +requests were proxied during the timeframe. Null latencies are not graphed in +Kong Manager; periods with null latencies appear as gaps in Vitals charts. + +#### Proxy Latency (Request) + +The Proxy Latency metrics are the min, max, and average values for the time, in milliseconds, that the Kong proxy spends processing API proxy requests. This includes time to execute plugins that run in the access phase and the DNS lookup time. This does not include time spent in Kong’s load balancer, time spent sending the request to the upstream, or time spent on the response. + +These metrics are referenced in the Vitals API with the following labels: `latency_proxy_request_min_ms`, `latency_proxy_request_max_ms`, `latency_proxy_request_avg_ms`. + +Latency is not reported when a request is prematurely ended by Kong (e.g., bad auth, rate limited, etc.). Note that this differs from the **Total Requests** metric that does count such requests. + +#### Upstream Latency + +The Upstream Latency metrics are the min, max, and average values for the time elapsed, in milliseconds, between Kong sending requests upstream and Kong receiving the first bytes of responses from upstream. + +These metrics are referenced in the Vitals API with the following labels: `latency_upstream_min_ms`, `latency_upstream_max_ms`, `latency_upstream_avg_ms`. + +### Datastore Cache + +#### Datastore Cache Hit/Miss + +The Datastore Cache Hit/Miss metrics are the count of requests to Kong's node-level datastore cache. When Kong workers need configuration information to respond to a given API proxy request, they first check their worker-specific cache (also known as L1 cache), then if the information isn’t available they check the node-wide datastore cache (also known as L2 cache). If neither cache contains the necessary information, Kong requests it from the datastore. + +A `Hit` indicates that an entity was retrieved from the data store cache. A `Miss` indicates that the record had to be fetched from the datastore. Not every API request will result in datastore cache access; some entities will be retrieved from Kong's worker-specific cache memory. + +These metrics are referenced in the Vitals API with the following labels: `cache_datastore_hits_total`, `cache_datastore_misses_total`. + +#### Datastore Cache Hit Ratio + +This metric contains the ratio of datastore cache hits to the total count of datastore cache requests. + +> **Note:** Datastore Cache Hit Ratio cannot be calculated for time indices with no hits and no misses. + +## Traffic Metrics + +Traffic metrics provide insight into which of your services are being used, who is using them, and how they are responding. + +### Request Counts + +#### Total Requests + + +This metric is the count of all API proxy requests received. This includes requests that were rejected due to rate-limiting, failed authentication, etc. + +This metric is referenced in the Vitals API with the following label: `requests_proxy_total`. + +#### Requests Per Consumer + +This metric is the count of all API proxy requests received from each specific consumer. Consumers are identified by credentials in their requests (e.g., API key, OAuth token) as required by the Kong Auth plugins in use. + +This metric is referenced in the Vitals API with the following label: `requests_consumer_total`. + +### Status Codes + +#### Total Status Code Classes + +This metric is the count of all status codes grouped by status code class (e.g. 4xx, 5xx). + +This metric is referenced in the Vitals API with the following label: `status_code_classes_total`. + +#### Total Status Codes per Service + +This metric is the total count of each specific status code for a given service. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_service_total`. + +#### Total Status Codes per Route + +This metric is the total count of each specific status code for a given route. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_route_total`. + +#### Total Status Codes per Consumer +This metric is the total count of each specific status code for a given consumer. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_consumer_total`. + +#### Total Status Codes per Consumer Per Route +This metric is the total count of each specific status code for a given consumer and route. + +This metric is referenced in the Vitals API with the following label: `status_codes_per_consumer_route_total`. diff --git a/app/gateway/2.7.x/vitals/vitals-prometheus-strategy.md b/app/gateway/2.7.x/vitals/vitals-prometheus-strategy.md new file mode 100644 index 000000000000..77503ecec561 --- /dev/null +++ b/app/gateway/2.7.x/vitals/vitals-prometheus-strategy.md @@ -0,0 +1,299 @@ +--- +title: Vitals with Prometheus +badge: enterprise +--- + +This document covers integrating Kong Vitals with a new or existing Prometheus +time-series server or cluster. Leveraging a time-series database for Vitals data +can improve request and Vitals performance in very-high traffic {{site.base_gateway}} +clusters (such as environments handling tens or hundreds of thousands of +requests per second), without placing addition write load on the database +backing the Kong cluster. + +For using Vitals with a database as the backend, refer to [Kong Vitals](/gateway/{{page.release}}/vitals/). + +## Lifecycle Overview + +Kong Vitals integrates with Prometheus using an intermediary data exporter, the [Prometheus StatsD exporter](https://github.com/prometheus/statsd_exporter). +This integration allows Kong to efficiently ship Vitals metrics to an outside process where data points +can be aggregated and made available for consumption by Prometheus, without impeding performance +within the Kong proxy itself. In this design, Kong writes Vitals metrics to the StatsD exporter +as [StatsD metrics](https://github.com/statsd/statsd/blob/master/docs/metric_types.md). Prometheus +scrapes this exporter as it would any other endpoint. Kong then queries Prometheus to retrieve and +display Vitals data via the API and Kong Manager. Prometheus does not ever directly scrape the Kong +nodes for time series data. A trivialized workflow looks as follows: + +![Single Node Example Data Flow](/assets/images/products/gateway/vitals/prometheus-single.png) + +It is not uncommon to separate Kong functionality amongst a cluster of nodes. For example, +one or more nodes serve only proxy traffic, while another node is responsible for serving the +Kong Admin API and Kong Manager. In this case, the node responsible for proxy traffic writes +the data to a StatsD exporter, and the node responsible for Admin API reads from Prometheus: + +![Multi Node Example Data Flow](/assets/images/products/gateway/vitals/prometheus-read-write.png) + +In either case, the StatsD exporter process can be run either as a standalone process/container +or as a sidecar/adjacent process within a VM. Note that in high-traffic environments, data aggregation +within the StatsD exporter process can cause significant CPU usage. In such cases, we recommend to +run Kong and StatsD processes on separate hardware/VM/container environments to avoid saturating CPU usage. + +## Set up Prometheus environment for Vitals + +### Download Prometheus + +The latest release of Prometheus can be found at the [Prometheus download page](https://prometheus.io/download/#prometheus). + +Prometheus should be running on a separate node from the one running Kong. +For users that are already using Prometheus in their infrastructure, it's +possible to use existing Prometheus nodes as Vitals storage backend. + +In this guide, we assume Prometheus is running on hostname `prometheus-node` +using default config that listens on port `9090`. + +### Download and configure StatsD exporter + +StatsD exporter is distributed as a Docker image. Pull the latest version +with the following command: + +```sh +docker pull kong/statsd-exporter-advanced:0.3.1 +``` + +The binary includes features like min/max gauges and Unix domain +socket support which are not supported in the public project. + +{:.important} +> This Docker image is a Kong fork of the Prometheus community project and the mapping rules linked below +> do not work with the public image. Ensure you are using the correct one. +> +> If you prefer to use the Prometheus community Helm chart to deploy the exporter, override the image +> and tag in the `values` file as shown below: +> +> ```yaml +> image: +> repository: kong/statsd-exporter-advanced +> tag: 0.3.1 +> ``` + +StatsD exporter needed to configured with a set of mapping rules to translate +the StatsD UDP events to Prometheus metrics. A default set of mapping rules can +be downloaded at +[statsd.rules.yaml](/code-snippets/statsd.rules.yaml). +Then start StatsD exporter with + +```bash +./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.listen-unixgram='' +``` + +The StatsD mapping rules file must be configured to match the metrics sent from +Kong. To learn how to customize the StatsD events name, please refer to +[Enable Vitals with Prometheus strategy in Kong](#enable-vitals-with-prometheus-strategy-in-kong) +section. + +StatsD exporter can run either on a separate node from Kong (to avoid resource +competition with Kong), or on the same host with Kong (to reduce unnecessary +network overhead). + +In this guide, we assume StatsD exporter is running on hostname `statsd-node`, +using default config that listens to UDP traffic on port `9125` and the metrics +in Prometheus Exposition Format are exposed on port `9102`. + +### Configure Prometheus to scrape StatsD exporter + +To configure Prometheus to scrape StatsD exporter, add the following section to +`scrape_configs` in `prometheus.yaml`. + +```yaml +scrape_configs: + - job_name: 'vitals_statsd_exporter' + scrape_interval: "5s" + static_configs: + - targets: ['statsd-node:9102'] +``` + +Please update `statsd-node` with the actual hostname that runs StatsD exporter. + +If you are using service discovery, it will be more convenient to configure +multiple StatsD exporters in Prometheus. Please refer to the +[`scape_configs`](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Cscrape_config%3E) +section of Prometheus document for further reading. + +By default, the Vitals graph in Kong Manager uses the configured target address +in the legend, which is named `instance` in the Prometheus metrics label. For some service +discovery setups where `instance` is `IP:PORT`, the user might want to relabel the `instance` +label to display a more meaningful hostname in the legend. +To do so, the user can also refer to the [`scape_configs`](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Cscrape_config%3E) +section and rewrite the `instance` label with the corresponding meta label. + +For example, in a Kubernetes environment, use the following relabel rules: + +```yaml +scrape_configs: + - job_name: 'vitals_statsd_exporter' + kubernetes_sd_configs: + # your SD config to filter statsd exporter pods + relabel_configs: + - source_labels: [__meta_kubernetes_pod_name] + action: replace + target_label: 'instance' +``` + +### Enable Vitals with Prometheus strategy in Kong + +You can change this in your configuration to enable Vitals with Prometheus: + +```bash +# via your Kong configuration file +vitals = on +vitals_strategy = prometheus +vitals_statsd_address = statsd-node:9125 +vitals_tsdb_address = prometheus-node:9090 +``` + +```bash +# or via environment variables +export KONG_VITALS=on +export KONG_VITALS_STRATEGY=prometheus +export KONG_VITALS_STATSD_ADDRESS=statsd-node:9125 +export KONG_VITALS_TSDB_ADDRESS=prometheus-node:9090 +``` + +{:.note} +> **Note**: In Hybrid Mode, configure [`vitals_strategy`](/gateway/{{page.release}}/reference/configuration/#vitals_strategy) +and [`vitals_tsdb_address`](/gateway/{{page.release}}/reference/configuration/#vitals_tsdb_address) +on both the control plane and all data planes. + +Please update `statsd-node` and `prometheus-node` with the actual hostname that +runs StatsD exporter and Prometheus. + +As with other Kong configurations, your changes take effect on `kong reload` or +`kong restart`. + +If you set `scrape_interval` in Prometheus other than the default value of `5` +seconds, you will also need to update the following: + +```bash +# via your Kong configuration file +vitals_prometheus_scrape_interval = new_value_in_seconds +``` + +```bash +# or via environment variables +export KONG_VITALS_PROMETHEUS_SCRAPE_INTERVAL=new_value_in_seconds +``` + +The above option configures `interval` parameter when querying Prometheus. +The value `new_value_in_seconds` should be equal or larger than +`scrape_interval` config in Prometheus. + +You can also configure Kong to send StatsD events with a different prefix from +the default value of `kong`. Make sure the prefix in statsd.rules +is same as that in Kong configuration: + +```bash +# via your Kong configuration file +vitals_statsd_prefix = kong-vitals +``` + +```bash +# or via environment variables +export KONG_VITALS_STATSD_PREFIX=kong-vitals +``` + +```yaml +# in statsd.rules +mappings: +# by API +- match: kong-vitals.api.*.request.count + name: "kong_requests_proxy" + labels: + job: "kong_metrics" +# follows other metrics +# ... +``` + +### Install Grafana dashboard + +If you use Grafana, you can import the Kong Vitals Prometheus dashboard to visualize the data. + +In your Grafana installation, click the **+** button in the sidebar, and choose **Import**. + +On the **Import** screen, find the **Grafana.com Dashboard** field and enter `11870`. Then, click **Load**. Optionally, you +can also download the JSON model from [https://grafana.com/grafana/dashboards/11870](https://grafana.com/grafana/dashboards/11870) and import it manually. + +On the next screen, select the **Prometheus** data source that is configured to scrape `statsd-exporter`, then +click **Import**. + +## Tuning and Optimization + +### StatsD exporter UDP buffer + +As the amount of concurrent requests increases, the length of the queue to store +unprocessed UDP events will grow as well. +It's necessary to increase the UDP read buffer size to avoid possible packet +dropping. + +To increase the UDP read buffer for the StatsD exporter process, run the binary +using the following example to set read buffer to around 3 MB: + +``` +./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.listen-unixgram='' \ + --statsd.read-buffer=30000000 +``` + +To increase the UDP read buffer for the host that's running, adding the +following example line to `/etc/sysctl.conf`: + +``` +net.core.rmem_max = 60000000 +``` + +And then apply the setting with root privilege: + +``` +# sysctl -p +``` + +### StatsD exporter with Unix domain socket + +It is possible to further reduce network overhead by deploying StatsD exporter +on the same node with Kong and let the exporter listen on local Unix domain +socket. + +```bash +./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.read-buffer=30000000 \ + --statsd.listen-unixgram='/tmp/statsd.sock' +``` + +By default the socket is created with permission `0755`, so that StatsD exporter + has to be running with the same user with Kong to allow Kong to write UDP + packets to the socket. To allow the exporter and Kong to run as different + users, the socket can be created with permission `0777` with the following: + +```bash +./statsd_exporter --statsd.mapping-config=statsd.rules.yaml \ + --statsd.read-buffer=30000000 \ + --statsd.listen-unixgram='/tmp/statsd.sock' \ + --statsd.unixsocket-umask="777" +``` + +## Exported Metrics + +With the above configuration, the Prometheus StatsD exporter will make available all +metrics as provided by the [standard Vitals configuration](/gateway/{{page.release}}/vitals/vitalsSpec.yaml). + +Additionally, the exporter process provides access to the default metrics exposed by the [Golang +Prometheus client library](https://prometheus.io/docs/guides/go-application/). These metric names +include the `go_` and `process_` prefixes. These data points are related specifically +to the StatsD exporter process itself, not Kong. Infrastructure teams may find this data +useful, but they are of limited value with respect to monitoring Kong behavior. + +## Accessing Vitals metrics from Prometheus + +You can also access Kong Vitals metrics in Prometheus and display on Grafana +or setup alerting rules. With the example StatsD mapping rules, all metrics are +labeled with `exported_job=kong_vitals`. With the above Prometheus scrape config +above, all metrics are also labeled with `job=vitals_statsd_exporter`. diff --git a/app/gateway/2.7.x/vitals/vitals-reports.md b/app/gateway/2.7.x/vitals/vitals-reports.md new file mode 100644 index 000000000000..77eb8d05158e --- /dev/null +++ b/app/gateway/2.7.x/vitals/vitals-reports.md @@ -0,0 +1,49 @@ +--- +title: Vitals Reports +badge: enterprise +--- + +Browse, filter, and view your data in a Vitals time-series report, and export the data into a comma-separated values (CSV) file. + +When generating a Vitals report, you can: +* Generate a report across all Workspaces or a single Workspace. +* Filter report parameters, such as object, metric, metric type, and values. +* Select the time period or interval for the report, such as minutes, hours, or days. +* View a line chart that automatically generates depending on the selected criteria. +* Export your report to a CSV file. + + +## Prerequisites + +InfluxDB database installed and configured. For more information, see +[Vitals with InfluxDB](/gateway/{{page.release}}/vitals/vitals-influx-strategy/). + +**Important**: The Vitals Reports feature is not compatible with a PostgreSQL or Cassandra database. If using one of these databases, the Reports button will not display on the Vitals view. + + +## Generate a Vitals Report + +To create a time-series report containing Vitals data, complete the steps in this section. + +1. On the Vitals view, click the **Reports** button. + +2. On the Reports page select the **Timeframe**, up to 12 hours, for which you want to create the report. + +3. Select the report criteria for the report: + + | Selection | Description | + |--------------------------|----------------------------------------------------------------------------------------------| + | *Report Type* | Consumer Requests: This report is for requests made by Consumers.
    Service Requests: This report is for services with a Service ID and name of the service that is stored in the {{site.base_gateway}} database.
    Cluster Latency: This report is the aggregation of two fields. | + | *Scope* | Drill down and filter for more detailed information. | + | *Interval* | Select the time interval to display in the report: weeks, hours, days, minutes. If you select an interval that is out of the available range, the results return zeroes. | + + +4. A Vitals report generates, starting with a summary of data in your report, including Id, Name, App Name, App Id, and Total. Note that the App Name and App Id are dependent on the Dev Portal App Registration plugin. For more information about status codes (2XX, 4XX, etc), see [_Vitals Metrics_](/gateway/{{page.release}}/vitals/vitals-metrics/). + +5. To download your report, click **Export**. A CSV file containing your Vitals report data downloads to your system. + +## Export Vitals Data to a CSV Report + +1. Create a Vitals report, as defined above in [Generate a Vitals Report](#generate-a-vitals-report). + +2. Click **Export** to download a CSV file to your system. diff --git a/app/gateway/2.7.x/vitals/vitalsSpec.yaml b/app/gateway/2.7.x/vitals/vitalsSpec.yaml new file mode 100644 index 000000000000..2cbcf24c9dfb --- /dev/null +++ b/app/gateway/2.7.x/vitals/vitalsSpec.yaml @@ -0,0 +1,847 @@ +swagger: '2.0' +info: + description: Vitals API + version: 2.4.0 + title: Vitals API +basePath: / +tags: + - name: health + description: Stats about the health of a Kong cluster + - name: traffic + description: Stats about traffic routed through Kong +schemes: + - http +paths: + /vitals: + get: + tags: + - vitals + summary: Get information about stats collected + description: '' + operationId: getVitalsInfo + produces: + - application/json + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/VitalsInfo' + /vitals/cluster: + get: + tags: + - health + summary: Get health stats for this Kong cluster + description: '' + operationId: getClusterStats + produces: + - application/json + parameters: + - name: interval + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ClusterVitalsTimeSeriesWithMetadata' + '400': + description: Invalid query params + /vitals/cluster/status_codes: + get: + deprecated: true + tags: + - traffic + summary: Get the status code classes returned across the cluster + description: This operation is deprecated. Use /status_code_classes. + operationId: getClusterStatusCodeStats + produces: + - application/json + parameters: + - name: interval + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ClusterVitalsStatusCodesWithMetadata' + '400': + description: Invalid query params + /vitals/nodes: + get: + tags: + - health + summary: Get health stats for all nodes + description: '' + operationId: getAllNodeStats + produces: + - application/json + parameters: + - name: interval + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/NodeVitalsTimeSeriesWithMetadata' + '400': + description: Invalid query params + '/vitals/nodes/{node_id}': + get: + tags: + - health + summary: Get stats for a specific node by UUID + description: '' + operationId: getNodeStatsByID + produces: + - application/json + parameters: + - name: node_id + type: string + in: path + description: Node to retrieve stats for + required: true + - name: interval + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + type: string + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/NodeVitalsTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested node + '/{workspace_name}/vitals/consumers/{consumer_id}/cluster': + get: + tags: + - traffic + deprecated: true + summary: Get count of requests for the given consumer across entire cluster + description: This operation is deprecated. Use /vitals/status_codes/by_consumer_and_route + operationId: getConsumerClusterStats + produces: + - application/json + parameters: + - name: workspace_name + type: string + in: path + description: Workspace containing the requested consumer. + required: true + - name: consumer_id + type: string + in: path + description: Consumer to retrieve stats for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/ClusterConsumersTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested consumer + /{workspace_name}/vitals/status_code_classes: + get: + tags: + - traffic + summary: Get status code classes for a cluster or workspace. + description: '' + operationId: getStatusCodeClassesByWorkspace + produces: + - application/json + parameters: + - name: workspace_name + type: string + in: path + description: >- + Optional parameter. If provided, returns status code classes for the + workspace; otherwise, returns them for the cluster + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested consumer + /{workspace_name}/vitals/status_codes/by_service: + get: + tags: + - traffic + summary: Get a time series of status codes returned by a given service + description: '' + operationId: getStatusCodesByService + produces: + - application/json + parameters: + - name: service_id + type: string + in: query + description: Service to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: workspace_name + type: string + in: path + description: Workspace containing the requested service. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested service + /{workspace_name}/vitals/status_codes/by_route: + get: + tags: + - traffic + summary: Get cluster-wide count of status for a given route + description: '' + operationId: getStatusCodesByRoute + produces: + - application/json + parameters: + - name: route_id + type: string + in: query + description: Route to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: workspace_name + type: string + in: path + description: Workspace containing the requested route. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested route + /{workspace_name}/vitals/status_codes/by_consumer: + get: + tags: + - traffic + summary: Get cluster-wide count of status for a given consumer + description: '' + operationId: getStatusCodesByRoute + produces: + - application/json + parameters: + - name: consumer_id + type: string + in: query + description: Route to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: true + type: string + - name: workspace_name + type: string + in: path + description: Workspace containing the requested consumer. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested route + '/{workspace_name}/vitals/status_codes/by_consumer_and_route': + get: + tags: + - traffic + summary: >- + Get status codes for all the routes called by the given consumer in the + given timeframe + description: '' + operationId: getStatusCodesByConsumerAndRoute + produces: + - application/json + parameters: + - name: consumer_id + type: string + in: query + description: Consumer to retrieve status codes for + required: true + - name: interval + type: string + in: query + description: Granularity of the time series (days, minutes or seconds) + required: true + - name: start_ts + in: query + description: Requested start of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: end_ts + in: query + description: Requested end of the time series, in Unix epoch format (seconds) + required: false + type: string + - name: workspace_name + type: string + in: path + description: Workspace containing the requested consumer and route. + required: true + responses: + '200': + description: successful operation + schema: + $ref: '#/definitions/StatusCodesByEntityTimeSeriesWithMetadata' + '400': + description: Invalid query params + '404': + description: Unable to find requested consumer +definitions: + ClusterVitalsMetadata: + properties: + level: + type: string + example: cluster + enum: + - cluster + - node + workspace_id: + type: string + description: UUID of workspace this time series is for + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - cache_datastore_hits_total + - cache_datastore_misses_total + - latency_proxy_request_min_ms + - latency_proxy_request_max_ms + - latency_upstream_min_ms + - latency_upstream_max_ms + - requests_proxy_total + - latency_proxy_request_avg_ms + - latency_upstream_avg_ms + StatusCodesByEntityMetadata: + properties: + entity_type: + type: string + example: service|route + entity_id: + type: string + example: + level: + type: string + example: cluster + enum: + - cluster + workspace_id: + type: string + description: UUID of the workspace this time series is for + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - status_codes_service|route_total + StatusCodesByEntityTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/StatusCodesByEntityMetadata' + stats: + $ref: '#/definitions/StatusCodesByEntityStats' + ClusterVitalsStatusCodesMetadata: + properties: + level: + type: string + example: cluster + enum: + - cluster + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - status_code_classes_total + ClusterVitalsStats: + properties: + cluster: + type: object + properties: + : + type: array + items: + type: integer + description: >- + List of stat values collected at "timestamp_n", in same order as + "meta.stat_labels" + example: + - 999 + - 130 + - 0 + - 35 + - 142 + - 528 + - 1146 + - 110 + - 156 + StatusCodesByEntityStats: + properties: + cluster: + type: object + description: Vitals status codes data available at the cluster level + properties: + : + type: object + properties: + : + type: integer + description: >- + The total count of a particular status code for the time + period + example: 1824 + ClusterVitalsStatusCodesStats: + properties: + cluster: + type: object + description: Vitals status codes data available at the cluster level + properties: + : + type: object + properties: + : + type: integer + description: >- + The total count of a particular status code class for the time + period + example: 1824 + ClusterVitalsTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/ClusterVitalsMetadata' + stats: + $ref: '#/definitions/ClusterVitalsStats' + ClusterVitalsStatusCodesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/ClusterVitalsStatusCodesMetadata' + stats: + $ref: '#/definitions/ClusterVitalsStatusCodesStats' + ClusterConsumersMetadata: + properties: + level: + type: string + example: cluster + enum: + - cluster + - node + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - requests_consumer_total + ClusterConsumersStats: + properties: + cluster: + type: object + properties: + : + type: integer + description: >- + List of stat values collected at "timestamp_n", in same order as + "meta.stat_labels" + example: 47 + ClusterConsumersTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/ClusterConsumersMetadata' + stats: + $ref: '#/definitions/ClusterConsumersStats' + NodeVitalsMetadata: + properties: + level: + type: string + example: node + enum: + - cluster + - node + workspace_id: + type: string + description: UUID of the workspace this time series is for + interval: + type: string + example: seconds + enum: + - seconds + - minutes + - days + interval_width: + type: number + example: 60 + earliest_ts: + type: integer + example: 1514508300 + latest_ts: + type: integer + example: 1514508480 + stat_labels: + type: array + items: + type: string + example: + - cache_datastore_hits_total + - cache_datastore_misses_total + - latency_proxy_request_min_ms + - latency_proxy_request_max_ms + - latency_upstream_min_ms + - latency_upstream_max_ms + - requests_proxy_total + - latency_proxy_request_avg_ms + - latency_upstream_avg_ms + nodes: + type: object + description: >- + table of node ids that contributed to this time series. This element + is not included on cluster-level requests. + properties: + : + type: object + description: The id of a node included in this time series. + properties: + hostname: + type: string + description: The name of the host where this node runs + NodeVitalsStats: + properties: + : + type: object + description: >- + The node this time series is for, or "cluster" if it's a cluster-level + time series. + properties: + : + type: array + items: + type: integer + description: >- + List of stat values collected at "timestamp_n", in same order as + "meta.stat_labels" + example: + - 999 + - 130 + - 0 + - 35 + - 142 + - 528 + - 1146 + - 110 + - 156 + NodeVitalsTimeSeriesWithMetadata: + type: object + properties: + meta: + $ref: '#/definitions/NodeVitalsMetadata' + stats: + $ref: '#/definitions/NodeVitalsStats' + VitalsInfo: + type: object + example: + stats: + cache_datastore_hits_total: + levels: + cluster: + intervals: + days: + retention_period_seconds: 63072000 + minutes: + retention_period_seconds: 90000 + seconds: + retention_period_seconds: 3600 + nodes: + intervals: + days: + retention_period_seconds: 63072000 + minutes: + retention_period_seconds: 90000 + seconds: + retention_period_seconds: 3600 + properties: + stats: + type: object + properties: + : + type: object + properties: + levels: + type: object + description: >- + Vitals data is tracked and aggregated at different levels (per + cluster, per node) + properties: + cluster: + type: object + description: Vitals data available at the cluster level + properties: + intervals: + type: object + description: >- + Vitals data is available at different intervals + (seconds, minutes, days) + properties: + days: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the days interval + minutes: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the minutes interval + seconds: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the seconds interval + nodes: + type: object + description: Vitals data available at the node level + properties: + intervals: + type: object + description: >- + Vitals data is available at different intervals + (seconds, minutes, days) + properties: + days: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the days interval + minutes: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the minutes interval + seconds: + type: object + properties: + retention_period_seconds: + type: integer + description: >- + Configured retention period (in seconds) for + the seconds interval diff --git a/app/gateway/changelog.md b/app/gateway/changelog.md index c4b2fbb32e18..97ecc1fc7eb1 100644 --- a/app/gateway/changelog.md +++ b/app/gateway/changelog.md @@ -1,8 +1,23 @@ --- -title: Kong Gateway Enterprise Changelog +title: Kong Gateway Changelog Archive no_version: true --- + + +This changelog covers Kong Gateway versions that have reached end of sunset support. +For archives of versions before 2.6, see the [Kong Gateway Enterprise changelog](/enterprise/changelog/). + +Looking for recent releases? See [https://docs.konghq.com/gateway/changelog/](https://docs.konghq.com/gateway/changelog/) for the latest changes. + +Archives: +- [Kong Gateway 3.x](#kong-gateway-3x) +- [Kong Gateway 2.x](#kong-gateway-2x) + +## Kong Gateway 3.x + +Archived Kong Gateway versions in the 3.x series. + ## 3.0.1.0 **Release Date** 2022/11/02 @@ -903,3 +918,982 @@ openid-connect [#9287](https://github.com/Kong/kong/pull/9287) * Bumped `lodash` for Dev Portal from 4.17.11 to 4.17.21 * Bumped `lodash` for Kong Manager from 4.17.15 to 4.17.21 + + +## Kong Gateway 2.x + +Archived Kong Gateway versions in the 2.x series from 2.6 and later. +For earlier versions, see the [Kong Gateway Enterprise archive changelog](/enterprise/changelog/). + +## 2.7.2.0 +**Release Date** 2022/04/07 + +### Fixes + +#### Enterprise + +* Fixed an issue with RBAC where `endpoint=/kong workspace=*` would not let the `/kong` endpoint be accessed from all workspaces +* Fixed an issue with RBAC where admins without a top level `endpoint=*` permission could not add any RBAC rules, even if they had `endpoint=/rbac` permissions. These admins can now add RBAC rules for their current workspace only. +* Kong Manager + * Enable the `search_user_info` option when using OpenID Connect (OIDC) + * Fix broken docs links on the Upstream page + * Serverless functions can now be saved when there is a comma in the provided value + * Custom plugins now show an Edit button when viewing the plugin configuration +* Keys are no longer rotated unexpectedly when a node restarts +* Add cache when performing RBAC token verification +* The log message "plugins iterator was changed while rebuilding it" was incorrectly logged as an `error`. This release converts it to the `info` log level. +* Fixed a 500 error when rate limiting counters are full with the Rate Limiting Advanced plugin + +#### Plugins + +* [HTTP Log](/hub/kong-inc/http-log/) (`http-log`) + * Include provided query string parameters when sending logs to the `http_endpoint` +* [Forward Proxy](/hub/kong-inc/forward-proxy/) (`forward-proxy`) + * Fix timeout issues with HTTPs requests by setting `https_proxy_host` to the same value as `http_proxy_host` + * Use lowercase when overwriting the `host` header + * Add support for basic authentication when using a secured proxy with HTTPS requests +* [StatsD Advanced](/hub/kong-inc/statsd-advanced/) (`statsd-advanced`) + * Added support for setting `workspace_identifier` to `workspace_name` +* [Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced/) (`rate-limiting-advanced`) + * Skip namespace creation if the plugin is not enabled. This prevents the error "[rate-limiting-advanced] no shared dictionary was specified" being logged. +* [Proxy Cache Advanced](/hub/kong-inc/proxy-cache-advanced/) (`proxy-cache-advanced`) + * Large files would not be cached due to memory usage, leading to a `X-Cache-Status:Miss` response. This has now been resolved +* [GraphQL Proxy Cache Advanced](/hub/kong-inc/graphql-proxy-cache-advanced/) (`graphql-proxy-cache-advanced`) + * Large files would not be cached due to memory usage, leading to a `X-Cache-Status:Miss` response. This has now been resolved +* [LDAP Auth Advanced](/hub/kong-inc/ldap-auth-advanced/) (`ldap-auth-advanced`) + * Support passwords that contain a `:` character + +### Dependencies + +* Bumped `openssl` from 1.1.1k to 1.1.1n to resolve CVE-2022-0778 [#8635](https://github.com/Kong/kong/pull/8635) +* Bumped `openresty` from 1.19.3.2 to 1.19.9.1 [#7727](https://github.com/Kong/kong/pull/7727) + + +## 2.7.1.2 +**Release Date** 2022/02/17 + +### Fixes + +#### Enterprise +* Fixed an issue with Kong Manager OIDC authentication, which caused the error +`“attempt to call method 'select_by_username_ignore_case' (a nil value)”` +and prevented login with OIDC. +* Fixed an issue where common names added to `cluster_allowed_common_names` did +not work. + +## 2.7.1.1 +**Release Date** 2022/02/04 + +### Fixes + +#### Enterprise +* Fixed a performance issue with Kong Manager, which occurred when admins had +access to multiple workspaces. +* Fixed the `attempt to index local 'workspace'` error, which occurred when +accessing Routes or Services using TLS. + +## 2.7.1.0 +**Release Date:** 2022/01/27 + +### Features + +#### Enterprise +* You can now configure [`cluster_max_payload`](/gateway/latest/reference/configuration/#cluster_max_payload) +for hybrid mode deployments. This configuration option sets the maximum payload +size allowed to be sent across from the control plane to the data plane. If your +environment has large configurations that generate `payload too big` errors +and don't get applied to the data planes, use this setting to adjust the limit. +* When using PKI for certificate verification in hybrid mode, you can now +configure a list of Common Names allowed to connect to a control plane with the +[`cluster_allowed_common_names`](/gateway/latest/reference/configuration/#cluster_allowed_common_names) +option. If not set, only data planes with the same parent domain as the control +plane cert are allowed. + +### Fixes + +#### Enterprise + +* Fixed an issue where OIDC authentication into Kong Manager failed when used +with Azure AD. +* Fixed a timer leak that caused the timers to be exhausted and failed to start +any other timers used by Kong, showing the error `too many pending timers`. +* Fix an issue where, if `data_plane_config_cache_mode` was set to `off`, the +data plane received no updates from the control plane. + +#### Core +* Reschedule resolve timer only when the previous one has finished. +[#8344](https://github.com/Kong/kong/pull/8344) +* Plugins, and any entities implemented with subchemas, now can use the +`transformations` and `shorthand_fields` properties, which were previously +only available for non-subschema entities. +[#8146](https://github.com/Kong/kong/pull/8146) + +#### Plugins + +* [Rate Limiting](/hub/kong-inc/rate-limiting/) (`rate-limiting`) + * Fixed a 500 error associated with performing arithmetic functions on a nil + value by adding a nil value check after performing `ngx.shared.dict` operations. + * Fixed a timer leak that caused the timers to be exhausted and failed to + start any other timers used by Kong, showing the error `too many pending timers`. + + Before, the plugin used one timer for each namespace maintenance process, + increasing timer usage on instances with a large number of rate limiting + namespaces. Now, it uses a single timer for all namespace maintenance. + +* [Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced/) (`rate-limiting-advanced`) + * Fixed a 500 error that occurred when consumer groups were enforced but no + proper configurations were provided. Now, if no specific consumer group + configuration exists, the consumer group defaults to the original plugin + configuration. + +* [Exit Transformer](/hub/kong-inc/exit-transformer/) (`exit-transformer`) + * Fix an issue where the Exit Transformer plugin + would break the plugin iterator, causing later plugins not to run. + +## 2.7.0.0 +**Release Date:** 2021/12/16 + +### Features + +#### Enterprise +* Kong Gateway now supports installations on [Debian 10 and 11](/gateway/2.7.x/install-and-run/debian/). +* This release introduces consumer groups, a new entity that lets you +manage custom rate limiting configuration for any defined subsets of consumers. +To use consumer groups for rate limiting, configure the [Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced/) +plugin with the `enforce_consumer_groups` and `consumer_groups` parameters, +and use the `/consumer_groups` endpoint to manage the groups. + + This is useful for managing consumers with same rate limiting settings, as you + can create a consumer group and one Rate Limiting Advanced plugin instance for + the group to reduce proxy delay. + + * [Consumer groups reference](/gateway/2.7.x/admin-api/consumer-groups/reference/) + * [Consumer groups examples](/gateway/2.7.x/admin-api/consumer-groups/examples/) + + This feature is currently not supported with declarative configuration. + +* The data plane configuration cache can now be encrypted or turned off entirely. + Two new configuration options have been added: + * [`data_plane_config_cache_mode`](/gateway/2.7.x/reference/configuration/#data_plane_config_cache_mode): + The cache can be `unencrypted`, `encrypted`, or `off`. + * [`data_plane_config_cache_path`](/gateway/2.7.x/reference/configuration/#data_plane_config_cache_path): + Use this setting to specify a custom path for the cache. +* The `/license/report` API endpoint now provides +[monthly throughput usage reports](/gateway/2.7.x/plan-and-deploy/licenses/report). + +#### Dev Portal +* The Dev Portal API now supports `sort_by={attribute}` and `sort_desc` +query parameters for sorted list results. +* Improvements to Dev Portal authentication with [OpenID Connect (OIDC)](/hub/kong-inc/openid-connect/): +If OIDC auth is enabled, the first time a user attempts to access the Dev Portal +using their IDP credentials, they are directed to a pre-filled registration form. +Submit the form to create a Dev Portal account, linking the account to your IDP. + + After linking, you can use your IDP credentials to directly access this Dev + Portal account. + +* Added TLSv1.3 support for the Dev Portal API and GUI. + +#### Kong Manager +* When [using OpenID Connect to secure Kong Manager](/gateway/2.7.x/configure/auth/kong-manager/oidc-mapping/), +you no longer need to create admins manually in Kong Manager and map their roles +to your identity provider. Instead, admins are created on first +login and their roles are assigned based on their group membership in your +IdP. This feature also partly resolves a problem with creating admins for both +Kong Manager and Dev Portal. + + {:.important} + > **Important:** This feature introduces a **breaking change**. The + `admin_claim` parameter replaces the `consumer_claim` parameter required by + previous versions. You must update your OIDC config file to keep OIDC + authentication working for Kong Manager. For more information, see + [OIDC Authenticated Group Mapping](/gateway/2.7.x/configure/auth/kong-manager/oidc-mapping/). + +* Kong Manager now provides a simplified, organized form for configuring the +OpenID Connect plugin. Users can now easily identify a common set of required +parameters to configure the plugin, and add custom configurations as needed. + +#### Core +* Service entities now have a required [`enabled` field](/gateway/2.7.x/admin-api/#service-object) +which defaults to `true`. When set to `false`, routes attached to the service +are not added to the proxy router. [#8113](https://github.com/Kong/kong/pull/8113) + + In hybrid mode: + * If `enabled` is set to `false` for a service, the service and its attached + routes and plugins are not exported to data planes. + * If `enabled` is set to `false` for a plugin, plugins are now also not + exported to data planes, regardless of the service setting. + +* DAOs in plugins must be listed in an array, so that their loading order is +explicit. Loading them in a hash-like table is now **deprecated**. + [#7942](https://github.com/Kong/kong/pull/7942) +* Added the ability to [route TLS traffic based on SNIs](/gateway/2.7.x/reference/proxy/#proxy-tls-passthrough-traffic) +without terminating the connection. + [#6757](https://github.com/Kong/kong/pull/6757) + +#### Performance + +In this release, we continued our work on better performance: + +* Improved the plugin iterator performance and JITability + [#7912](https://github.com/Kong/kong/pull/7912) + [#7979](https://github.com/Kong/kong/pull/7979) +* Simplified the Kong core context read and writes for better performance + [#7919](https://github.com/Kong/kong/pull/7919) +* Reduced proxy long tail latency while reloading DB-less config + [#8133](https://github.com/Kong/kong/pull/8133) + +#### PDK + +* Added two new functions for the `body_filter` phase: +[`kong.response.get_raw_body`](/gateway/2.7.x/pdk/kong.response/) and +[`kong.response.set_raw_body`](/gateway/2.7.x/pdk/kong.response/). + [#7887](https://github.com/Kong/kong/pull/7877) + +#### Plugins + +* [OpenID Connect](/hub/kong-inc/openid-connect/) (`openid-connect`) + * Added support for JWT algorithm RS384. + * The plugin now allows Redis Cluster nodes to be specified by hostname + through the `session_redis_cluster_nodes` field, which + is helpful if the cluster IPs are not static. + +* [Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced/) (`rate-limiting-advanced`) + * Added the `enforce_consumer_groups` and `consumer_groups` parameters, + which introduce support for consumer groups. With consumer groups, you can + manage custom rate limiting configuration for any defined subsets of consumers. + +* [Forward Proxy](/hub/kong-inc/forward-proxy/) (`forward-proxy`) + * Added two proxy authentication parameters, `auth_username` and `auth_password`. + +* [Mocking](/hub/kong-inc/mocking/) (`mocking`) + * Added the `random_examples` parameter. Use this setting to randomly select + one example from a set of mocked responses. + +* [IP-Restriction](/hub/kong-inc/ip-restriction/) (`ip-restriction`) + * Response status and message can now be customized + through configurations `status` and `message`. + [#7728](https://github.com/Kong/kong/pull/7728) + + Thanks [timmkelley](https://github.com/timmkelley) for the patch! + +* [Datadog](/hub/kong-inc/datadog/) (`datadog`) + * Added support for the `distribution` metric type. + [#6231](https://github.com/Kong/kong/pull/6231) + + Thanks [onematchfox](https://github.com/onematchfox) for the patch! + + * Allow service, consumer, and status tags to be customized through new + plugin configurations `service_tag`, `consumer_tag`, and `status_tag`. + [#6230](https://github.com/Kong/kong/pull/6230) + + Thanks [onematchfox](https://github.com/onematchfox) for the patch! + +* [gRPC Gateway](/hub/kong-inc/grpc-gateway/) (`grpc-gateway`) and [gRPC Web](/hub/kong-inc/grpc-web/) (`grpc-web`) + * Both plugins now share the Timestamp transcoding and included `.proto` + files features. + [#7950(https://github.com/Kong/kong/pull/7950) + +* [gRPC Gateway](/hub/kong-inc/grpc-gateway/) (`grpc-gateway`) + * This plugin now processes services and methods defined in imported + `.proto` files. + [#8107](https://github.com/Kong/kong/pull/8107) + +* [Rate-Limiting](/hub/kong-inc/rate-limiting/) (`rate-limiting`) + Added support for Redis SSL through configuration properties + `redis_ssl` (can be set to `true` or `false`), `redis_ssl_verify`, and + `redis_server_name`. + [#6737](https://github.com/Kong/kong/pull/6737) + + Thanks [gabeio](https://github.com/gabeio) for the patch! + +#### Plugin encryption + +* Several fields have been marked as encrypted on plugins. +If [keyring encryption](/gateway/2.7.x/plan-and-deploy/security/db-encryption/) +is enabled, these fields will be encrypted: + + * ACME: `account_email`, `eab_kid`, and `eab_hmac_kid` + * AWS Lambda: `aws_key` and `aws_secret` + * Azure Functions: `apikey` and `clientid` + * Basic Auth: `basicauth_credentials.password` + * HTTP Log: `http_endpoint` + * LDAP Auth Advanced: `ldap_password` + * Loggly: `key` + * OAuth2: `config.provision_key` parameter value and the + `oauth2_credentials.provision_key` field + * OpenID Connect: `client_id`, `client_secret`, `session_auth`, and + `session_redis_auth` + * Session: `secret` + * Vault: `vaults.vault_token` and `vault_credentials.secret_token` + + {:.note} + > **Note**: There is a known issue with encrypting deeply nested fields in + certain plugins. For plugins with fields that are marked as encrypted but + currently not working, see the [Known Issues section](#known-issues). + +### Fixes + +#### Enterprise +* Fixed an issue with Vitals report generation. If running Vitals with InfluxDB +and attempting to generate a report containing any status codes outside of +2XX, 4XX, or 5XX, report generation would fail. With this fix, proxied traffic +outside of the expected codes will not cause errors, and instead appear as +count totals in Vitals reports. + +* Fixed a latency issue in hybrid mode. Previously, applying a large number of +configuration changes to a data plane simultaneously caused high latency in all +upstream requests. + +* Users can now successfully delete admins with the `super-admin` role from +any workspace, as long as they have the correct permissions, and the associated +Consumer entity will be deleted as well. This frees up the username for a new +user. Previously, deleting an admin with a `super-admin` role from a different +workspace than where it was originally created did not delete the associated +Consumer entity, and the username would remain locked. For example, if the +admin was created in workspace `dev` and deleted from workspace `QA`, this +issue would occur. + +* Phone home metrics are now sent over TLS, meaning that any analytics data +on Kong Gateway usage now travels through an encrypted connection. + +#### Dev Portal +* Dev Portal OpenID Connect authentication now properly redirects users based on +the values of `login_redirect_uri` and `forbidden_redirect_uri` set in `portal_auth`. +If these values are not set in `portal_auth`, redirect values are taken from the +Portal templates file, `portal.conf.yaml`. + +* When using OpenID Connect as the Dev Portal authentication method, updates to +Developers now correctly propagate to their associated Consumers. + +* Fixed links in Dev Portal footer. + +* Improved accessibility of the Dev Portal, fixing various issues related to +labels, names, headings, and color contrast: + * Keyboard-accessible response examples and "Try it out" sections + * Form inputs now have labels + * Selectable elements now all have accessible names + * Unique IDs for active elements + * Heading levels only increase by one, and are in the correct order + * Improved contrast of buttons + +* Fixed info tooltip crash and rendering issue when viewing the Dev Portal app +registration service list. + +* Fixed the Dev Portal Application Services list to allow pagination. + +* Fixed a table border styling issue in Dev Portal. + +#### Kong Manager +* Fixed an issue with icon alignment in Kong Manager, where the **Delete** +(garbage can) icon overlapped with the **View** link and caused users to +accidentally click **Delete**. + +#### Core + +* Fixed an issue where the `pluginsocket.proto` file was missing for Go plugins. +* Balancer caches are now reset on configuration reload. + [#7924](https://github.com/Kong/kong/pull/7924) +* Configuration reload no longer causes a new DNS-resolving timer to be started. + [#7943](https://github.com/Kong/kong/pull/7943) +* Fixed problem when bootstrapping multi-node Cassandra clusters, where migrations could attempt + insertions before a schema agreement occurred. + [#7667](https://github.com/Kong/kong/pull/7667) +* Fixed an intermittent botting error which happened when a custom plugin had interdependent entity schemas + on its custom DAO and they were loaded in an incorrect order. + [#7911](https://github.com/Kong/kong/pull/7911) +* Fixed an issue where `encrypted=true` would apply to the main plugin object, +instead of each plugin subschema. + +#### PDK + +* `kong.log.inspect` log level is now `debug` instead of `warn`. It also renders + textboxes more cleanly now. + [#7815](https://github.com/Kong/kong/pull/7815) + +#### Plugins + +* [LDAP Authentication](/hub/kong-inc/ldap-auth/) (`ldap-auth`) + * Fixed issue where the basic authentication header was not parsed correctly + when the password contained a colon (`:`). + [#7977](https://github.com/Kong/kong/pull/7977) + + Thanks [beldahanit](https://github.com/beldahanit) for reporting the issue! + +* [Prometheus](/hub/kong-inc/prometheus/) (`prometheus`) + * Hid Upstream Target health metrics on the control plane, as the control plane + doesn't initialize the balancer and doesn't have any real metrics to show. + [#7992](https://github.com/Kong/kong/pull/7922) + +* [Request Validator](/hub/kong-inc/request-validator/) (`request-validator`) + * Reverted the change in parsing multiple values, as arrays in version 1.1.3 + headers and query-args as `primitive` are now validated individually when duplicates are provided, instead of merging them as an array. + * Whitespace around CSV values is now dropped since it is not significant according to the RFC (whitespace is optional). + * Bumped `openapi3-deserialiser` to 2.0.0 to enable the changes. + +* [Forward Proxy](/hub/kong-inc/forward-proxy/) (`forward-proxy`) + * This plugin no longer uses deprecated features of the `lua-resty-http` + dependency, which previously added deprecation warnings to the DEBUG log. + * This plugin no longer sets a Host header if the `upstream_host` is an empty + string. + +* [OAuth2 Introspection](/hub/kong-inc/oauth2-introspection/) (`oauth2-introspection`) + * This plugin no longer uses deprecated features of the `lua-resty-http` + dependency, which previously added deprecation warnings to the DEBUG log. + +* [GraphQL Rate Limiting Advanced](/hub/kong-inc/graphql-rate-limiting-advanced/) (`graphql-rate-limiting-advanced`) + * Fixed plugin initialization code causing HTTP 500 status codes after + enabling the plugin. + +* [mTLS Auth](/hub/kong-inc/mtls-auth/) (`mtls-auth`) + * Fixed an issue where CRL cache was not properly invalidated, causing all + certificates to appear invalid. + +* [Proxy Cache Advanced](/hub/kong-inc/proxy-cache-advanced/) (`proxy-cache-advanced`) + * Fixed the `function cannot be called in access phase` error, which occurred + when the plugin was called in the log phase. + +* [Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced/) (`rate-limiting-advanced`) + * Fixed the schema entity check for `config.limit` and `config.window_size` count + when the number of configured window sizes and limits parameters are not equal. + +### Dependencies + +* Bumped `go-pdk` used in tests from v0.6.0 to v0.7.1 +[#7964](https://github.com/Kong/kong/pull/7964) +* Bumped `grpcurl` from 1.8.2 to 1.8.5 +[#7959](https://github.com/Kong/kong/pull/7959) +* Bumped `lua-pack` from 1.0.5 to 2.0.0 +[#8004](https://github.com/Kong/kong/pull/8004) +* Dependency on `luaossl` is removed. +* `lua-resty-openapi3-deserializer` (library dependency) + * Reverted the header fix in `1.1.0`. For primitive types, the values are + returned as plain strings, not as an array. Duplicate values must now be + offered individually for deserialization. + * Stripped whitespace from headers since it is not significant according to + the RFC. + +### Deprecated +* Kong Immunity is deprecated, removed, and not available in Kong Gateway. + +* Cassandra as a backend database for Kong Gateway +is deprecated with this release and will be removed in a future version. + + The target for Cassandra removal is the Kong Gateway 3.4 release. + Starting with the Kong Gateway 3.0 release, some new features might + not be supported with Cassandra. Our intent is to provide our users with ample + time and alternatives for satisfying the use cases that they have been able to + address with Cassandra. + +* The old `BasePlugin` module is deprecated and will be removed in a future version of Kong. + See porting tips in the [documentation](/gateway/2.7.x/plugin-development/custom-logic/#migrating-from-baseplugin-module). +* Hash syntax for plugin DAOs is deprecated. Plugin DAOs should be arrays +instead of hashes. + +### Known issues +* There's a bug in Kong Gateway which prevents keyring encryption from working on +deeply nested fields in plugins, so the `encrypted=true` setting does not have any +effect on the following plugins and fields: + * JWT Signer: the fields `d`, `p`, `q`, `dp`, `dq`, `qi`, and `k` inside + `jwt_signer_jwks.previous[...].` and `jwt_signer_jwks.keys[...]` + * Kafka Log: `config.authentication.user` and `config.authentication.password` + * Kafka Upstream: `config.authentication.user` and `config.authentication.password` + * OpenID Connect: the fields `d`, `p`, `q`, `dp`, `dq`, `qi`, `oth`, `r`, `t`, and `k` + inside `openid_connect_jwks.previous[...].` and `openid_connect_jwks.keys[...]` + +* Consumer groups are not supported in declarative configuration with +decK. If you have consumer groups in your configuration, decK will ignore them. + +* If you are using SSL certificates with custom plugins, you may need to set certificate phase in `ngc.ctx`. + +## 2.6.1.0 +**Release Date** 2022/04/07 + +### Fixes + +#### Enterprise + +* Fixed an issue with RBAC where `endpoint=/kong workspace=*` would not let the `/kong` endpoint be accessed from all workspaces +* Fixed an issue with RBAC where admins without a top level `endpoint=*` permission could not add any RBAC rules, even if they had `endpoint=/rbac` permissions. These admins can now add RBAC rules for their current workspace only. + +#### Plugins + +* [HTTP Log](/hub/kong-inc/http-log/) (`http-log`) + * Include provided query string parameters when sending logs to the `http_endpoint` + +### Dependencies + +* Bumped `openssl` from 1.1.1k to 1.1.1n to resolve CVE-2022-0778 [#8635](https://github.com/Kong/kong/pull/8635) +* Bumped `luarocks` from 3.7.1 to 3.8.0 [#8630](https://github.com/Kong/kong/pull/8630) +* Bumped `openresty` from 1.19.3.2 to 1.19.9.1 [#7727](https://github.com/Kong/kong/pull/7727) + +## 2.6.0.4 +**Release Date** 2022/02/10 + +### Fixes + +#### Enterprise +* Fixed an issue with Kong Manager OIDC authentication, which caused the error +`“attempt to call method 'select_by_username_ignore_case' (a nil value)”` +and prevented login with OIDC. + + + +## 2.6.0.3 +**Release Date:** 2022/01/27 + +### Features + +#### Enterprise +* You can now configure [`cluster_max_payload`](/gateway/latest/reference/configuration/#cluster_max_payload) +for hybrid mode deployments. This configuration option sets the maximum payload +size allowed to be sent across from the control plane to the data plane. If your +environment has large configurations that generate `payload too big` errors +and don't get applied to the data planes, use this setting to adjust the limit. + +### Fixes + +#### Enterprise + +* Phone home metrics are now sent over TLS, meaning that any analytics data +on Kong Gateway usage now travels through an encrypted connection. +* Fixed an issue where OIDC authentication into Kong Manager failed when used +with Azure AD. +* Fixed a timer leak that caused the timers to be exhausted and failed to start +any other timers used by Kong, showing the error `too many pending timers`. +* Fixed an issue with icon alignment in Kong Manager, where the **Delete** +(garbage can) icon overlapped with the **View** link and caused users to +accidentally click **Delete**. + +#### Dev Portal +* Fixed the Dev Portal Application Services list to allow pagination. +* Fixed a table border styling issue. +* Fixed issues with modal accessibility. + +#### Plugins + +* [Rate Limiting](/hub/kong-inc/rate-limiting/) (`rate-limiting`) and +[Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced) (`rate-limiting-advanced`) + * Fixed a timer leak that caused the timers to be exhausted and failed to + start any other timers used by Kong, showing the error `too many pending timers`. + + Before, the plugin used one timer for each namespace maintenance process, + increasing timer usage on instances with a large number of rate limiting + namespaces. Now, it uses a single timer for all namespace maintenance. + +## 2.6.0.2 +**Release Date:** 2021/12/03 + +### Fixes + +#### Dev Portal + +* Fixed links in Dev Portal footer. + +* Improved accessibility of the Dev Portal, fixing various issues related to +labels, names, headings, and color contrast: + * Keyboard-accessible response examples and "Try it out" sections + * Form inputs now have labels + * Selectable elements now all have accessible names + * Unique IDs for active elements + * Heading levels only increase by one, and are in the correct order + * Improved contrast of buttons + +* Fixed the Dev Portal API `/applications` endpoint to only accept allowed +fields in a PATCH request. + +* Fixed info tooltip crash and rendering issue when viewing the Dev Portal app +registration service list. + +#### Plugins +- [OpenID Connect](/hub/kong-inc/openid-connect/) (`openid-connect`) + - The plugin now allows Redis Cluster nodes to be specified by hostname + through the `session_redis_cluster_nodes` field, which + is helpful if the cluster IPs are not static. + +## 2.6.0.1 +**Release Date:** 2021/11/18 + +### Fixes + +#### Enterprise +- Fixed an issue with Vitals report generation. If running Vitals with InfluxDB +and attempting to generate a report containing any status codes outside of +2XX, 4XX, or 5XX, report generation would fail. With this fix, proxied traffic +outside of the expected codes will not cause errors, and instead appear as +count totals in Vitals reports. + +- Fixed a latency issue in hybrid mode. Previously, applying a large number of +configuration changes to a Data Plane simultaneously caused high latency in all +upstream requests. + +- Fixed accessibility issues related to non-unique IDs in the Dev Portal. + +- When using OpenID Connect as the Dev Portal authentication method, updates to +Developers now correctly propagate to their associated Consumers. + +- Users can now successfully delete admins with the `super-admin` role from +any workspace, as long as they have the correct permissions, and the associated +Consumer entity will be deleted as well. This frees up the username for a new +user. Previously, deleting an admin with a `super-admin` role from a different +workspace than where it was originally created did not delete the associated +Consumer entity, and the username would remain locked. For example, if the +admin was created in workspace `dev` and deleted from workspace `QA`, this +issue would occur. + +### Dependencies +* Bumped kong-redis-cluster from `1.1-0` to `1.2.0`. + - With this update, if the entire cluster is restarted and starts up using + new IP addresses, the cluster client can recover automatically. + +## 2.6.0.0 +**Release date:** 2021/10/14 + +### Features + +#### Enterprise + +#### Core +This release includes the addition of a new schema entity validator: `mutually_exclusive`. Before, the +`only_one_of` validator required at least one of the fields included be configured. This new entity validator allows +only one or neither of the fields be configured. +[#7765](https://github.com/Kong/kong/pull/7765) + +#### Configuration +- Enable IPV6 on `dns_order` as unsupported experimental feature. + [#7819](https://github.com/Kong/kong/pull/7819). +- The template renderer can now use `os.getenv`. + [#6872](https://github.com/Kong/kong/pull/6872). + +#### Hybrid Mode +- Data plane is able to eliminate some unknown fields when Control Plane is using a more modern version. + [#7827](https://github.com/Kong/kong/pull/7827). + +#### Admin API +- Added support for the HTTP HEAD method for all Admin API endpoints. + [#7796](https://github.com/Kong/kong/pull/7796) +- Added better support for OPTIONS requests. Previously, the Admin API replied the same on all OPTIONS requests, + where as now OPTIONS request will only reply to routes that our Admin API has. Non-existing routes will have a + 404 returned. Additionally, the Allow header was added to responses. Both Allow and Access-Control-Allow-Methods + now contain only the methods that the specific API supports. + [#7830](https://github.com/Kong/kong/pull/7830) + +#### Plugins +- **New plugin:** [jq](/hub/kong-inc/jq/) (`jq`) + The jq plugin enables arbitrary jq transformations on JSON objects included in API requests or responses. +- [Kafka Log](/hub/kong-inc/kafka-log/) (`kafka-log`) + The Kafka Log plugin now supports TLS, mTLS, and SASL auth. SASL auth includes support for PLAIN, SCRAM-SHA-256, + and delegation tokens. +- [Kafka Upstream](/hub/kong-inc/kafka-upstream/) (`kafka-upstream`) + The Kafka Upstream plugin now supports TLS, mTLS, and SASL auth. SASL auth includes support for PLAIN, SCRAM-SHA-256, + and delegation tokens. +- [Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced/) (`rate-limiting-advanced`) + - The Rate Limiting Advanced plugin now has a new identifier type, `path`, which allows rate limiting by + matching request paths. + - The plugin now has a `local` strategy in the schema. The local strategy automatically sets `config.sync_rate` to -1. + - The highest sync-rate configurable was a 1 second interval. This sync-rate has been increased by reducing + the minimum allowed interval from 1 to 0.020 second (20ms). +- [OPA](/hub/kong-inc/opa/) (`opa`) + The OPA plugin now has a request path parameter, which makes setting policies on a path easier for administrators. +- [Canary](/hub/kong-inc/canary/) (`canary`) + The Canary plugin now has the option to hash on the header (falls back on IP, and then random). +- [OpenID Connect](/hub/kong-inc/openid-connect/) (`openid-connect`) + Upgrade to v2.1.0 to maintain version compatibility with older data planes. + - Features from v2.0.x include the following: + - The OpenID Connect plugin can now handle JWT responses from a `userinfo` endpoint. + - The plugin now supports JWE Introspection. + - Feature from to v2.1.x includes the following: + - The plugin now has a new param, `by_username_ignore_case`, which allows `consumer_by` username values to be + matched case-insensitive with Identity Provider claims. +- [Request Transformer Advanced](/hub/kong-inc/request-transformer-advanced/) (`request-transformer-advanced`) + - This release includes a fix for the URL encode transformed path. The plugin now uses PDK functions to set upstream URI + by replacing `ngx.var.upstream_uri` so the urlencode is taken care of. +- [AWS-Lambda](/hub/kong-inc/aws-lambda/) (`aws-lambda`) + The plugin will now try to detect the AWS region by using `AWS_REGION` and + `AWS_DEFAULT_REGION` environment variables (when not specified with the plugin configuration). + This allows users to specify a 'region' on a per Kong node basis, adding the ability to invoke the + Lambda function in the same region where Kong is located. + [#7765](https://github.com/Kong/kong/pull/7765) +- [Datadog](/hub/kong-inc/datadog/) (`datadog`) + The Datadog plugin now allows `host` and `port` config options be configured from environment variables, + `KONG_DATADOG_AGENT_HOST` and `KONG_DATADOG_AGENT_PORT`. This update enables users to set + different destinations on a per Kong node basis, which makes multi-DC setups easier and in Kubernetes helps + with the ability to run the Datadog agents as a daemon-set. + [#7463](https://github.com/Kong/kong/pull/7463) +- [Prometheus](/hub/kong-inc/prometheus/) (`prometheus`) + The Prometheus plugin now includes a new metric, `data_plane_cluster_cert_expiry_timestamp`, to expose the Data Plane's `cluster_cert` + expiry timestamp for improved monitoring in Hybrid Mode. + [#7800](https://github.com/Kong/kong/pull/7800). +- [GRPC-Gateway](/hub/kong-inc/grpc-gateway/) (grpc-gateway) + - Fields of type `.google.protobuf.Timestamp` on the gRPC side are now + transcoded to and from ISO8601 strings in the REST side. + [#7538](https://github.com/Kong/kong/pull/7538) + - URI arguments like `..?foo.bar=x&foo.baz=y` are interpreted as structured + fields, equivalent to `{"foo": {"bar": "x", "baz": "y"}}`. + [#7564](https://github.com/Kong/kong/pull/7564) +- [Request Termination](/hub/kong-inc/request-termination/) (`request-termination`) + - The Request Termination plugin now includes a new `trigger` config option, which makes the plugin + only activate for any requests with a header or query parameter named like the trigger. This config option + can be a great debugging aid, without impacting actual traffic being processed. + [#6744](https://github.com/Kong/kong/pull/6744). + - The `request-echo` config option was added. If set, the plugin responds with a copy of the incoming request. + This config option eases troubleshooting when Kong Gateway is behind one or more other proxies or LB's, + especially when combined with the new `trigger` option. + [#6744](https://github.com/Kong/kong/pull/6744). + +### Dependencies +* Bumped `openresty` from 1.19.3.2 to [1.19.9.1](https://openresty.org/en/changelog-1019009.html) + [#7430](https://github.com/Kong/kong/pull/7727) +* Bumped `openssl` from `1.1.1k` to `1.1.1l` + [7767](https://github.com/Kong/kong/pull/7767) +* Bumped `lua-resty-http` from 0.15 to 0.16.1 + [#7797](https://github.com/kong/kong/pull/7797) +* Bumped `Penlight` to 1.11.0 + [#7736](https://github.com/Kong/kong/pull/7736) +* Bumped `lua-resty-http` from 0.15 to 0.16.1 + [#7797](https://github.com/kong/kong/pull/7797) +* Bumped `lua-protobuf` from 0.3.2 to 0.3.3 + [#7656](https://github.com/Kong/kong/pull/7656) +* Bumped `lua-resty-openssl` from 0.7.3 to 0.7.4 + [#7657](https://github.com/Kong/kong/pull/7657) +* Bumped `lua-resty-acme` from 0.6 to 0.7.1 + [#7658](https://github.com/Kong/kong/pull/7658) +* Bumped `grpcurl` from 1.8.1 to 1.8.2 + [#7659](https://github.com/Kong/kong/pull/7659) +* Bumped `luasec` from 1.0.1 to 1.0.2 + [#7750](https://github.com/Kong/kong/pull/7750) +* Bumped `lua-resty-ipmatcher` to 0.6.1 + [#7703](https://github.com/Kong/kong/pull/7703) + +### Fixes + +#### Enterprise +- This release includes a fix for an issue with the Vitals InfluxDB timestamp generation when inserting metrics. +- Kong Gateway (Enterprise) no longer exports `consumer_reset_secrets`. +- Fixes an issue where keyring data was not being properly generated and activated + on a Kong process start (for example, kong start). +- Kong Gateway now returns keyring-encrypted fields early when a decrypt attempt is made, giving you time + to import the keys so Kong Gateway can recognize the decrypted fields. Before if there were data fields + keyring-encrypted in the database, Kong Gateway attempted to decrypt them on the `init*` phases (`init` or `init_worker` + phases - when the Kong process is started), and you would get errors like "no request found". **Keys must still be imported after the Kong process is started.** +- The [Keyring Encryption](/gateway/latest/kong-enterprise/db-encryption/) feature is no longer in an alpha quality state. +- This release includes a fix to the CentOS Docker image builds, ensuring CentOS 7 images are properly generated. + +#### Core +- Balancer retries now correctly set the `:authority` pseudo-header on balancer retries. + [#7725](https://github.com/Kong/kong/pull/7725). +- Healthchecks are now stopped while the Balancer is being recreated. + [#7549](https://github.com/Kong/kong/pull/7549). +- Fixed an issue in which a malformed `Accept` header could cause unexpected HTTP 500. + [#7757](https://github.com/Kong/kong/pull/7757). +- Kong no longer removes `Proxy-Authentication` request header and `Proxy-Authenticate` response header. + [#7724](https://github.com/Kong/kong/pull/7724). +- Fixed an issue where Kong would not sort correctly Routes with both regex and prefix paths. + [#7695](https://github.com/Kong/kong/pull/7695) + +#### Hybrid Mode +- Ensure data plane config thread is terminated gracefully, preventing a semi-deadlocked state. + [#7568](https://github.com/Kong/kong/pull/7568) + +##### CLI +- `kong config parse` no longer crashes when there's a Go plugin server enabled. + [#7589](https://github.com/Kong/kong/pull/7589). + +##### Configuration +- Declarative Configuration parser now prints more correct errors when printing unknown foreign references. + [#7756](https://github.com/Kong/kong/pull/7756). +- YAML anchors in Declarative Configuration are properly processed. + [#7748](https://github.com/Kong/kong/pull/7748). + +##### Admin API +- `GET /upstreams/:upstreams/targets/:target` no longer returns 404 when target weight is 0. + [#7758](https://github.com/Kong/kong/pull/7758). + +##### PDK +- `kong.response.exit` now uses customized "Content-Length" header when found. + [#7828](https://github.com/Kong/kong/pull/7828). + +##### Plugins +- [ACME](/hub/kong-inc/acme/) (`acme`) + Dots in wildcard domains are escaped. + [#7839](https://github.com/Kong/kong/pull/7839). +- [Prometheus](/hub/kong-inc/prometheus/) (`prometheus`) + Upstream's health info now includes previously missing `subsystem` field. + [#7802](https://github.com/Kong/kong/pull/7802). +- [Proxy-Cache](/hub/kong-inc/proxy-cache/) (`proxy-cache`) + Fixed an issue where the plugin would sometimes fetch data from the cache but not return it. + [#7775](https://github.com/Kong/kong/pull/7775) + +## 2.6.0.0 (beta1) +**Release date:** 2021/10/04 + +### Features + +#### Enterprise + +#### Core +This release includes the addition of a new schema entity validator: `mutually_exclusive`. Before, the +`only_one_of` validator required at least one of the fields included be configured. This new entity validator allows +only one or neither of the fields be configured. +[#7765](https://github.com/Kong/kong/pull/7765) + +#### Configuration +- Enable IPV6 on `dns_order` as unsupported experimental feature. + [#7819](https://github.com/Kong/kong/pull/7819). +- The template renderer can now use `os.getenv`. + [#6872](https://github.com/Kong/kong/pull/6872). + +#### Hybrid Mode +- Data plane is able to eliminate some unknown fields when Control Plane is using a more modern version. + [#7827](https://github.com/Kong/kong/pull/7827). + +#### Admin API +- Added support for the HTTP HEAD method for all Admin API endpoints. + [#7796](https://github.com/Kong/kong/pull/7796) +- Added better support for OPTIONS requests. Previously, the Admin API replied the same on all OPTIONS requests, + where as now OPTIONS request will only reply to routes that our Admin API has. Non-existing routes will have a + 404 returned. Additionally, the Allow header was added to responses. Both Allow and Access-Control-Allow-Methods + now contain only the methods that the specific API supports. + [#7830](https://github.com/Kong/kong/pull/7830) + +#### Plugins +- **New plugin:** [jq](/hub/kong-inc/jq/) (`jq`) + The jq plugin enables arbitrary jq transformations on JSON objects included in API requests or responses. +- [Kafka Log](/hub/kong-inc/kafka-log/) (`kafka-log`) + The Kafka Log plugin now supports TLS, mTLS, and SASL auth. SASL auth includes support for PLAIN, SCRAM-SHA-256, + and delegation tokens. +- [Kafka Upstream](/hub/kong-inc/kafka-upstream/) (`kafka-upstream`) + The Kafka Upstream plugin now supports TLS, mTLS, and SASL auth. SASL auth includes support for PLAIN, SCRAM-SHA-256, + and delegation tokens. +- [Rate Limiting Advanced](/hub/kong-inc/rate-limiting-advanced/) (`rate-limiting-advanced`) + - The Rate Limiting Advanced plugin now has a new identifier type, `path`, which allows rate limiting by + matching request paths. + - The plugin now has a `local` strategy in the schema. The local strategy automatically sets `config.sync_rate` to -1. + - The highest sync-rate configurable was a 1 second interval. This sync-rate has been increased by reducing + the minimum allowed interval from 1 to 0.020 second (20ms). +- [OPA](/hub/kong-inc/opa/) (`opa`) + The OPA plugin now has a request path parameter, which makes setting policies on a path easier for administrators. +- [Canary](/hub/kong-inc/canary/) (`canary`) + The Canary plugin now has the option to hash on the header (falls back on IP, and then random). +- [OpenID Connect](/hub/kong-inc/openid-connect/) (`openid-connect`) + Upgrade to v2.1.0 to maintain version compatibility with older data planes. + - Features from v2.0.x include the following: + - The OpenID Connect plugin can now handle JWT responses from a `userinfo` endpoint. + - The plugin now supports JWE Introspection. + - Feature from to v2.1.x includes the following: + - The plugin now has a new param, `by_username_ignore_case`, which allows `consumer_by` username values to be + matched case-insensitive with Identity Provider claims. +- [AWS-Lambda](/hub/kong-inc/aws-lambda/) (`aws-lambda`) + The plugin will now try to detect the AWS region by using `AWS_REGION` and + `AWS_DEFAULT_REGION` environment variables (when not specified with the plugin configuration). + This allows users to specify a 'region' on a per Kong node basis, adding the ability to invoke the + Lambda function in the same region where Kong is located. + [#7765](https://github.com/Kong/kong/pull/7765) +- [Datadog](/hub/kong-inc/datadog/) (`datadog`) + The Datadog plugin now allows `host` and `port` config options be configured from environment variables, + `KONG_DATADOG_AGENT_HOST` and `KONG_DATADOG_AGENT_PORT`. This update enables users to set + different destinations on a per Kong node basis, which makes multi-DC setups easier and in Kubernetes helps + with the ability to run the Datadog agents as a daemon-set. + [#7463](https://github.com/Kong/kong/pull/7463) +- [Prometheus](/hub/kong-inc/prometheus/) (`prometheus`) + The Prometheus plugin now includes a new metric, `data_plane_cluster_cert_expiry_timestamp`, to expose the Data Plane's `cluster_cert` + expiry timestamp for improved monitoring in Hybrid Mode. + [#7800](https://github.com/Kong/kong/pull/7800). +- [GRPC-Gateway](/hub/kong-inc/grpc-gateway/) (grpc-gateway) + - Fields of type `.google.protobuf.Timestamp` on the gRPC side are now + transcoded to and from ISO8601 strings in the REST side. + [#7538](https://github.com/Kong/kong/pull/7538) + - URI arguments like `..?foo.bar=x&foo.baz=y` are interpreted as structured + fields, equivalent to `{"foo": {"bar": "x", "baz": "y"}}`. + [#7564](https://github.com/Kong/kong/pull/7564) +- [Request Termination](/hub/kong-inc/request-termination/) (`request-termination`) + - The Request Termination plugin now includes a new `trigger` config option, which makes the plugin + only activate for any requests with a header or query parameter named like the trigger. This config option + can be a great debugging aid, without impacting actual traffic being processed. + [#6744](https://github.com/Kong/kong/pull/6744). + - The `request-echo` config option was added. If set, the plugin responds with a copy of the incoming request. + This config option eases troubleshooting when Kong Gateway is behind one or more other proxies or LB's, + especially when combined with the new `trigger` option. + [#6744](https://github.com/Kong/kong/pull/6744). + +### Dependencies +* Bumped `openresty` from 1.19.3.2 to [1.19.9.1](https://openresty.org/en/changelog-1019009.html) + [#7430](https://github.com/Kong/kong/pull/7727) +* Bumped `openssl` from `1.1.1k` to `1.1.1l` + [7767](https://github.com/Kong/kong/pull/7767) +* Bumped `lua-resty-http` from 0.15 to 0.16.1 + [#7797](https://github.com/kong/kong/pull/7797) +* Bumped `Penlight` to 1.11.0 + [#7736](https://github.com/Kong/kong/pull/7736) +* Bumped `lua-resty-http` from 0.15 to 0.16.1 + [#7797](https://github.com/kong/kong/pull/7797) +* Bumped `lua-protobuf` from 0.3.2 to 0.3.3 + [#7656](https://github.com/Kong/kong/pull/7656) +* Bumped `lua-resty-openssl` from 0.7.3 to 0.7.4 + [#7657](https://github.com/Kong/kong/pull/7657) +* Bumped `lua-resty-acme` from 0.6 to 0.7.1 + [#7658](https://github.com/Kong/kong/pull/7658) +* Bumped `grpcurl` from 1.8.1 to 1.8.2 + [#7659](https://github.com/Kong/kong/pull/7659) +* Bumped `luasec` from 1.0.1 to 1.0.2 + [#7750](https://github.com/Kong/kong/pull/7750) +* Bumped `lua-resty-ipmatcher` to 0.6.1 + [#7703](https://github.com/Kong/kong/pull/7703) + +### Fixes + +#### Enterprise +- This release includes a fix for an issue with the Vitals InfluxDB timestamp generation when inserting metrics. +- Kong Gateway (Enterprise) no longer exports `consumer_reset_secrets`. +- Fixes an issue where keyring data was not being properly generated and activated + on a Kong process start (for example, kong start). +- Kong Gateway now returns keyring-encrypted fields early when a decrypt attempt is made, giving you time + to import the keys so Kong Gateway can recognize the decrypted fields. Before if there were data fields + keyring-encrypted in the database, Kong Gateway attempted to decrypt them on the `init*` phases (`init` or `init_worker` + phases - when the Kong process is started), and you would get errors like "no request found". **Keys must still be imported after the Kong process is started.** +- The [Keyring Encryption](/gateway/latest/kong-enterprise/db-encryption/) feature is no longer in an alpha quality state. + +#### Core +- Balancer retries now correctly set the `:authority` pseudo-header on balancer retries. + [#7725](https://github.com/Kong/kong/pull/7725). +- Healthchecks are now stopped while the Balancer is being recreated. + [#7549](https://github.com/Kong/kong/pull/7549). +- Fixed an issue in which a malformed `Accept` header could cause unexpected HTTP 500. + [#7757](https://github.com/Kong/kong/pull/7757). +- Kong no longer removes `Proxy-Authentication` request header and `Proxy-Authenticate` response header. + [#7724](https://github.com/Kong/kong/pull/7724). +- Fixed an issue where Kong would not sort correctly Routes with both regex and prefix paths. + [#7695](https://github.com/Kong/kong/pull/7695) + +#### Hybrid Mode +- Ensure data plane config thread is terminated gracefully, preventing a semi-deadlocked state. + [#7568](https://github.com/Kong/kong/pull/7568) + +##### CLI +- `kong config parse` no longer crashes when there's a Go plugin server enabled. + [#7589](https://github.com/Kong/kong/pull/7589). + +##### Configuration +- Declarative Configuration parser now prints more correct errors when printing unknown foreign references. + [#7756](https://github.com/Kong/kong/pull/7756). +- YAML anchors in Declarative Configuration are properly processed. + [#7748](https://github.com/Kong/kong/pull/7748). + +##### Admin API +- `GET /upstreams/:upstreams/targets/:target` no longer returns 404 when target weight is 0. + [#7758](https://github.com/Kong/kong/pull/7758). + +##### PDK +- `kong.response.exit` now uses customized "Content-Length" header when found. + [#7828](https://github.com/Kong/kong/pull/7828). + +##### Plugins +- [ACME](/hub/kong-inc/acme/) (`acme`) + Dots in wildcard domains are escaped. + [#7839](https://github.com/Kong/kong/pull/7839). +- [Prometheus](/hub/kong-inc/prometheus/) (`prometheus`) + Upstream's health info now includes previously missing `subsystem` field. + [#7802](https://github.com/Kong/kong/pull/7802). +- [Proxy-Cache](/hub/kong-inc/proxy-cache/) (`proxy-cache`) + Fixed an issue where the plugin would sometimes fetch data from the cache but not return it. + [#7775](https://github.com/Kong/kong/pull/7775)