diff --git a/docs/guides/api-gateway/add-traffic-policy.mdx b/docs/guides/api-gateway/add-traffic-policy.mdx new file mode 100644 index 000000000..a0e432e12 --- /dev/null +++ b/docs/guides/api-gateway/add-traffic-policy.mdx @@ -0,0 +1,302 @@ +--- +title: Add API gateway traffic management policies +description: Learn how to add and compose Traffic Policy rules, like authentication and rate limiting, to all or some of your API services. +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; +import Auth0 from "./img/auth0-create-api.png"; + +ngrok's API gateway is designed for composability, allowing you to pick and +choose from many [Traffic Policy +actions](/docs/traffic-policy/actions) and order them in many ways to +manage API traffic according to your needs. + +With our common pattern of using a cloud endpoint to route traffic to internal +agent endpoints, you can centrally manage certain policies like rate limiting or +authentication, then compose additional policies onto specific internal agent +endpoints and API services. + +If you haven't yet deployed ngrok as your API gateway, start with one of these +tutorials: + +- [Get started with an API gateway](/docs/guides/api-gateway/get-started) +- [Deploy an API gateway in Kubernetes](/docs/guides/api-gateway/kubernetes) +- [Deploy a multicloud API gateway](/docs/guides/api-gateway/multicloud) + +## Add a rate limiting policy to all API services + +We recommend you add a rate limiting policy on your cloud endpoint to protect +all your services from unintentional misuse and malicious attacks. + +When you apply rate limiting to your cloud endpoint, then forward traffic to one +or more internal URLs, then ngrok applies the policy equally across all your API +services. + +The Traffic Policy file below: + +1. Allows up to `10` requests per IP in a `60s` window. +2. Rejects requests that exceed the rate limiting `capacity` with a `429` error response. +3. Forwards all requests not subject to the rate limit to an internal endpoint. + You will need to edit this action, and potentially add additional + `forward-internal` actions, based on your routing topology. + +```yaml title="policy.yaml" mode=traffic-policy +on_http_request: + - actions: + - type: rate-limit + config: + name: Only allow 10 requests per minute + algorithm: sliding_window + capacity: 10 + rate: 60s + bucket_key: + - conn.client_ip + - actions: + - type: forward-internal + config: + url: https://foo.internal +``` + +Apply the rule to your cloud endpoint with the dashboard or API. + + + + + Navigate to the [Endpoints](https://dashboard.ngrok.com/endpoints) section + of the ngrok dashboard and click on the cloud endpoint to edit. + + Paste in the YAML above and click **Save** to apply the Traffic Policy rules. + + + + + Save the YAML above into a file named `policy.yaml` or similar. + + Use the ngrok CLI to update your endpoint based on its `id`. + + ``` + ngrok api endpoints update \ + {ENDPOINT_ID} \ + --traffic-policy "$(cat policy.yaml)" + ``` + + :::tip + If you don't remember your cloud endpoint's `id`, run `ngrok api endpoints list` and find it from the list. + ::: + + + + + +### Test your rate limiting policy + +You can test the rate limiting action by running the following command, +substituting the appropriate value for `{YOUR_NGROK_DOMAIN}`: + +```bash +for i in `seq 1 50`; do curl -X GET -w '%{http_code}' https://{YOUR_NGROK_DOMAIN}/ ; done +``` + +You'll see a few normal responses until you hit the rate limit, and then you'll +see `429` errors returned. + +## Add a security policy to all API services + +The JWT validation policy action allows you to integrate your ngrok endpoints +with your existing authentication provider. This example provides step-by-step +instructions for integrating with Auth0, but you can configure JWT validation +for any OAuth provider. + +### Define your API in Auth0 + +1. Log in to your [Auth0 tenant dashboard](https://manage.auth0.com/dashboard). +1. Select **Applications > APIs**, then **+ Create API**. +1. Name your API whatever you'd like. +1. Replace the value of the **Identifier** field with `{YOUR_NGROK_DOMAIN}`. +1. Leave the default values for **JSON Web Token (JWT) Profile \*** and **JSON + Web Token Signing Algorithm \***. +1. Click **Create**. + +Auth0 Create API + +### Access your JWT + +Upon creating your new API, Auth0 will create an associated application under +**Applications > APIs** in the left navigation bar. + +Navigate to your application, and click on the `Test` tab. Here, you will +find a signed, fully functional JWT, as well as examples of how to programmatically +generate one. + +### Update your Traffic Policy rules with the `validate-jwt` action + +The Traffic Policy file below: + +1. Integrates ngrok with your authentication provider so ngrok can validate JWTs + passed in requests to your API. +2. Rejects requests without a `Authorization: Bearer ...` header or valid token. +3. Forwards all authenticated requests to an internal endpoint. You will need to + edit this action, and potentially add additional `forward-internal` actions, + based on your routing topology. + +```yaml title="policy.yaml" traffic-policy +on_http_request: + - actions: + - type: "jwt-validation" + config: + issuer: + allow_list: + - value: "https://{YOUR_AUTH0_TENANT_ID}.us.auth0.com/" + audience: + allow_list: + - value: "https://{YOUR_NGROK_DOMAIN}" + http: + tokens: + - type: "jwt" + method: "header" + name: "Authorization" + prefix: "Bearer " + jws: + allowed_algorithms: + - "RS256" + keys: + sources: + additional_jkus: + - "https://{YOUR_AUTH0_TENANT_ID}.us.auth0.com/.well-known/jwks.json" + - actions: + - type: "forward-internal" + config: + url: "https://foo.internal" +``` + +Replace `{YOUR_AUTH0_TENANT_ID}` and `{YOUR_NGROK_DOMAIN}` and apply the rule to +your cloud endpoint with the dashboard or API. + +You can test the JWT validation policy, substituting your domain for +`{YOUR_NGROK_DOMAIN}` and the JWT obtained from the Auth0 dashboard for +`{YOUR_JWT}`: + +```bash +curl -X GET https://{YOUR_NGROK_DOMAIN}/ \ + --header "Authorization: Bearer {YOUR_JWT}" +``` + +By authenticating yourself against ngrok's JWT validation, you'll get the +expected response. If you include an invalid token, you'll see a `403 Forbidden` +error, and if you send a request with no `Authorization` header, you'll get `401 +Unauthorized` error. + +## Compose policies on specific API services + +In certain cases, you'll want to apply Traffic Policy rules to just one API +service—in those cases, you should update your internal agent endpoint with a +Traffic Policy file. + +### Example with URL rewrites + +The [`url-rewrite` Traffic Policy +action](/docs/traffic-policy/actions/url-rewrite/) lets you to modify the +incoming request URL before it reaches your API service and invisibly to the +user—perfect for routing user requests without exposing details about your +internal systems. + +To rewrite one path to another: + +```yaml title="url-rewrite.yaml" mode=traffic-policy +on_http_request: + - expressions: + - "req.url.path == '/foo'" + actions: + - type: url-rewrite + config: + from: /foo + to: /bar +``` + +To rewrite multiple URLs using regular expressions: + +``` +on_http_request: + - expressions: + - req.url.path.startsWith('/products') + actions: + - type: url-rewrite + config: + from: /foo/?([.*]+)? + to: /bar/$1 +``` + +Restart the ngrok agent on the same internal URL, while also specifying your new +Traffic Policy file. + +``` +ngrok http 8080 --url https://foo.internal --traffic-policy-file=url-rewrite.yaml +``` + +:::tip +If you're using other configuration flags, like `--pooling-enabled`, make +sure you add those to the command above. +::: + +When you send a request to the `/foo` path, your API service will respond as +though it had come from the `/bar` path. + +### Example with the `circuit-breaker` action + +For example, one API service is running on a machine with less system resources, +making it more suseptible to errors during peak load. You can implement the +[`circuit-breaker` Traffic Policy +action](/docs/traffic-policy/actions/circuit-breaker) on just the internal +agent endpoint that forwards traffic to that service for additional protection. + +Create a new Traffic Policy file named `circuit-breaker.yaml` on the system +where this internal agent endpoint runs. To help you see how it works, the +following `circuit-breaker` rule sets an intentionally low volume threshold that +allows `10` requests in a `60s` window before tripping the circuit breaker for +`2m`. + +```yaml title="circuit-breaker.yaml" mode=traffic-policy +on_http_request: + - actions: + - type: circuit-breaker + config: + error_threshold: 0 + volume_threshold: 10 + window_duration: 60s + tripped_duration: 2m + enforce: true +``` + +Restart the ngrok agent on the same internal URL, while also specifying your new +Traffic Policy file. + +``` +ngrok http 8080 --url https://foo.internal --traffic-policy-file=circuit-breaker.yaml +``` + +:::tip +If you're using other configuration flags, like `--pooling-enabled`, make +sure you add those to the command above. +::: + +You can test this behavior out by sending multiple `curl` requests to your APIs +in quick succession to trip the circuit breaker. + +## What's next? + +You've now adding common traffic management policies to your ngrok API gateway +at both your cloud and internal agent endpoints, allowing you to centrally +manage certain rules and compose others as needed. + +Explore other opportunities to manage and take action on API traffic in our +[Traffic Policy documentation](/docs/traffic-policy). + +Check out your [Traffic +Inspector](https://dashboard.ngrok.com/observability/traffic-inspector) +([documentation](/docs/obs/traffic-inspection)) to observe, modify, and +replay requests across your API gateway. diff --git a/docs/guides/api-gateway/get-started.mdx b/docs/guides/api-gateway/get-started.mdx index a1a262cf4..368b8f947 100644 --- a/docs/guides/api-gateway/get-started.mdx +++ b/docs/guides/api-gateway/get-started.mdx @@ -1,5 +1,5 @@ --- -title: Get started - Deliver and secure APIs in production +title: Get started with ngrok's API gateway tags: - guides - API @@ -10,8 +10,6 @@ tags: import Auth0 from "./img/auth0-create-api.png"; -# Get started - Deliver and secure APIs in production - You've developed a world-class API, and now you want to make it available for clients to access. This guide takes you from bringing your API online in one line to configuring an API gateway that simplifies routing, security, contract management, protocol translation, and more, providing a single point of entry for clients and services accessing your APIs. diff --git a/docs/guides/api-gateway/kubernetes.mdx b/docs/guides/api-gateway/kubernetes.mdx index 6922d66a6..f2a58c34b 100644 --- a/docs/guides/api-gateway/kubernetes.mdx +++ b/docs/guides/api-gateway/kubernetes.mdx @@ -1,12 +1,11 @@ --- +title: Deploy an API gateway in Kubernetes description: Deploy ngrok's Kubernetes Operator onto your cluster for unified ingress and advanced traffic shaping with K8s-native interfaces. --- import TabItem from "@theme/TabItem"; import Tabs from "@theme/Tabs"; -# Deliver and secure ingress for APIs in Kubernetes - You currently have a K8s cluster with an API (micro)service and want to deliver it to production with additional features and protection, like rate limiting, authentication, and DDoS protection. diff --git a/docs/guides/api-gateway/multicloud.mdx b/docs/guides/api-gateway/multicloud.mdx new file mode 100644 index 000000000..cd6a8323f --- /dev/null +++ b/docs/guides/api-gateway/multicloud.mdx @@ -0,0 +1,311 @@ +--- +title: Deploy a multicloud API gateway +description: In this tutorial, you'll learn how to load balance API services across multiple clouds and apply common multicloud traffic patterns. +--- + +import TabItem from "@theme/TabItem"; +import Tabs from "@theme/Tabs"; + +You've developed a world-class API, and now you want to make it available online +on not just one cloud provider, but two or more. + +Aside from the challenges involved in any multicloud deployment, you're looking +for a multicloud API gateway that allows you to: + +- Consistently apply security and traffic management policy in one place +- Provide a single pane of glass for observability +- Work identically in every cloud or environment + +## What you'll learn + +In this tutorial, you'll learn how to implement ngrok as a multicloud API gateway +with these broad steps: + +1. Set up the common pattern of using a single cloud endpoint to route all API + traffic to internal agent endpoints. +2. Use endpoint pooling to enable dead-simple load balancing between replicas of + your API service. +3. Connect non-replicated API services with additional internal agent endpoints. + +## What you'll need + +- **An ngrok account**: [Sign up](https://dashboard.ngrok.com/signup) for for + free if you don't already have one. +- **Your authtoken**: [Create an + authtoken](https://dashboard.ngrok.com/authtokens) using the ngrok dashboard. +- **A reserved domain**: [Reserve a domain](https://dashboard.ngrok.com/domains) + in the ngrok dashboard or using the [ngrok + API](/docs/api/resources/reserved-domains/#create-reserved-domain). + - You can choose from an ngrok subdomain or bring your own [custom branded + domain](/docs/guides/other-guides/how-to-set-up-a-custom-domain), like + `https://api.example.com`. + - We'll refer to this domain as `{YOUR_NGROK_DOMAIN}` throughout the guide. +- **The ngrok agent**: [Download](https://download.ngrok.com) the appropriate + version and install it on the same machine or network as the API service you + want to make available via ngrok's API gateway. +- (optional) **An API key**: [Create an ngrok API + key](https://dashboard.ngrok.com/api-keys/new) if you'd like to use the ngrok + API to manage your cloud endpoints. + +:::info +This guide uses endpoint pools, which are not yet generally available. To use +them, you must [request access to the developer +preview](https://dashboard.ngrok.com/developer-preview). +::: + +## Deploy a demo API service (optional) + +If you don't yet have API services you'd like to bring online with a multicloud +API gateway, or just want to quickly wire up a POC using ngrok, we recommend +running multiple "replicas" of our [ngrok demo +API](https://github.com/ngrok-samples/api-demo), which responds with details +about the request. + +Assuming you have Docker installed on the systems where your API services run, +you can deploy a container listening on port `4000`. + +```shell +docker run -p 4000:4000 -e MESSAGE='Hello from cloud A!' -d joelatngrok/api-demo +``` + +Spin up the same service on your other cloud providers as replicas. Change the +`MESSAGE` environment variable to help you later see which replica and which +clouds respond to your requests. + +## Add your API services to an endpoint pool + +When your create multiple endpoints with the same URL and binding, ngrok pools +them by default, load-balancing traffic between them. This can improve your +API's performance and resiliency. + +In one cloud, create an internal agent endpoint on an internal URL, like +`https://foo.internal`. Replace `4000` if you've brought your own API service. + +``` +ngrok http 4000 --url https://foo.internal --pooling-enabled +``` + +Run the same command for each replica of your API service on other clouds. + +Your API service replicas are now pooled and load-balanced, but not yet +accessible on the public internet. To fix that, you need two things: + +1. A cloud endpoint for traffic routing and centralized policy management. +2. A Traffic Policy rule that forwards traffic from your cloud endpoint to + `https://foo.internal`. + +## Create a cloud endpoint + +Cloud endpoints are persistent, always-on endpoints that you can manage with the +ngrok dashboard or API. + +You centrally control your traffic management and security policy on your cloud +endpoint, then forward traffic to your endpoint pool. That's much easier than trying +to synchronize policies across multiple replicas and >1 cloud. + + + + + First, log into the [ngrok dashboard](https://dashboard.ngrok.com). Click **Endpoints → + New**. + + Leave the **Binding** value **Public**, then enter the domain name you reserved earlier. Click **Create Cloud Endpoint**. + + With your cloud endpoint created, you'll see a default Traffic Policy in the dashboard. Paste in the YAML below to apply the rule. + + ```yaml title="policy.yaml" mode=traffic-policy + on_http_request: + - actions: + - type: forward-internal + config: + url: https://foo.internal + binding: internal + ``` + + Click **Save** to apply your changes. + + + + + The `ngrok` CLI provides a helpful wrapper around the [ngrok API](/docs/api/index), which you can use to create a cloud endpoint and apply a file containing Traffic Policy rules. + + Create a new file named `policy.yaml` on your local workstation with the following YAML. + + ```yaml title="policy.yaml" mode=traffic-policy + on_http_request: + - actions: + - type: forward-internal + config: + url: https://foo.internal + binding: internal + ``` + + Create a cloud endpoint on `{YOUR_NGROK_DOMAIN}`, passing your `policy.yaml` file as an option. + + ```shell + ngrok api endpoints create \ + --bindings public \ + --url https://{YOUR_NGROK_DOMAIN} + --traffic-policy "$(cat policy.yaml)" + ``` + + You'll get a `201` response—save the value of `id`, as you'll need it again later to continue configuring the Traffic Policy applied to your cloud endpoint. + + + + + +## Access your API services + +At this point, your multicloud API gateway is ready for traffic! Why don't you +give it a go? + +```bash +curl -X GET https://{YOUR_NGROK_DOMAIN} +``` + +If you're using our demo API, you'll see a response like: + +```json +{ + "message": "Hello from cloud A!", + "host": "localhost:4000", + "req_headers": { + "host": "localhost:4000", + "user-agent": "curl/8.5.0", + "accept": "*/*" + }, + "method": "GET", + "url": "/", + "time": "2025-02-06T21:44:23.116Z", + "status": 200 +} +``` + +Try a few more times, and you'll see `Hello from cloud B!` instead—proof you're +load balancing between clouds. + +Now is the time to start getting even more from Traffic Policy, our configuration +language for managing traffic. You can attach Traffic Policy rules to both your +cloud and agent endpoints, allowing you to compose some rules across all your +APIs and others to individual upstream services or replicas. + +See our tutorial on [API gateway traffic +management](/docs/guides/api-gateway/add-traffic-policy) for details. + +## Extend your multicloud API gateway with non-replicated services + +So far, you've deployed multiple replicas of a single API service and added load +balancing with an endpoint pool. + +What if you have more than one API service you'd like to make available behind a +multicloud API gateway? Or you've acquired a new business and want to integrate +their API services into your existing API gateway? + +To make this work, you need to add additional `forward-internal` actions and +implement a strategy for routing to different upstream services based on the +attributes of incoming requests. + +Let's assume you want to start a new `bar` service, which runs on port +`9090`. Create a new internal agent endpoint on a unique URL, like +`https://bar.internal`, to separate it from your endpoint pool. + +``` +ngrok http 9090 --url https://bar.internal +``` + +If you send another request to `{YOUR_NGROK_DOMAIN}`, ngrok forwards it to +`https://foo.internal` because your Traffic Policy rules don't yet contain a +strategy for routing traffic to multiple API services. ngrok has a few common +patterns to fix that. + +### Route by path + +Path-based routing lets you direct traffic to different backend services +based on the value of the path. + +The Traffic Policy file below: + +1. Routes requests to `https://{YOUR_NGROK_DOMAIN}/foo` to the + `https://foo.internal` endpoint pool. +2. Routes requests to `https://{YOUR_NGROK_DOMAIN}/bar` to the + `https://bar.internal` agent endpoint. +3. Uses the [`custom-response` + action](/docs/traffic-policy/actions/custom-response) to capture requests to + any other path and respond with a generic `403` error. + +```yaml title="policy.yaml" traffic-policy +on_http_request: + - name: "Route the /foo/ path to service foo" + expressions: + - req.url.path.startsWith('/foo') + actions: + - type: forward-internal + config: + url: https://foo.internal + - name: "Route the /bar/* path to service bar" + expressions: + - req.url.path.startsWith('/bar') + actions: + - type: forward-internal + config: + url: https://bar.internal + - name: "Custom response for other paths" + actions: + - type: custom-response + config: + status_code: 403 +``` + +Apply this Traffic Policy rule to your cloud endpoint through the dashboard or +API to start forwarding traffic. + +### Route by headers + +You can also route to endpoints based on the dynamic value of a header with [CEL +interpolation](/docs/traffic-policy/concepts/cel-interpolation). + +The Traffic Policy file below: + +1. Checks whether requests contain a `x-api` header, and if so, forwards to the + internal URL with the same name using CEL interpolation. +2. Uses the [`custom-response` + action](/docs/traffic-policy/actions/custom-response) to capture requests + without an appropriate header and respond with a generic `403` + error. + +```yaml title="policy.yaml" traffic-policy +on_http_request: + - name: "Forward traffic to API service based on `x-api` header value." + expressions: + - "req.headers['x-api']" + actions: + - type: forward-internal + config: + url: https://${getReqHeader(‘x-api’)[0]}.internal + - name: "Custom response for requests without expected headers" + actions: + - type: custom-response + config: + status_code: 403 +``` + +Apply this Traffic Policy rule to your cloud endpoint through the dashboard or +API to forward traffic based on the header values, like `x-api: foo` or `x-api: bar`. + +## What's next? + +You've now brought your multicloud APIs online with ngrok's API gateway, which +includes features like DDoS protection and global load balancing. + +Next up, we recommend you: + +- Continue your API gateway tutorial by [adding and composing traffic management + policies](/docs/guides/api-gateway/add-traffic-policy) to finish offloading + non-functional requirements, like rate limiting and authentication, to your + ngrok API gateway. +- Check out your [Traffic + Inspector](https://dashboard.ngrok.com/observability/traffic-inspector) + ([documentation](/docs/obs/traffic-inspection)) to observe, modify, and + replay requests across your API gateway. +- Explore other opportunities to manage and take action on API traffic in our + [Traffic Policy documentation](/docs/traffic-policy/index). diff --git a/sidebars.js b/sidebars.js index db781f8dd..dc7a3f42d 100644 --- a/sidebars.js +++ b/sidebars.js @@ -430,22 +430,61 @@ const sidebars = { }, { type: "html", - value: "", + value: "", }, { - label: "Guides", + label: "API Gateway", type: "category", - link: { type: "doc", id: "guides/index" }, items: [ - { type: "autogenerated", dirName: "guides" }, + "guides/api-gateway/get-started", + "guides/api-gateway/kubernetes", + "guides/api-gateway/multicloud", + "guides/api-gateway/add-traffic-policy", + ], + }, + { + label: "Device Gateway", + type: "category", + link: { type: "doc", id: "guides/device-gateway/index" }, + items: [{ type: "autogenerated", dirName: "guides/device-gateway" }], + }, + { + label: "Identity Aware Proxy", + type: "category", + link: { type: "doc", id: "guides/identity-aware-proxy/index" }, + items: [ + { type: "autogenerated", dirName: "guides/identity-aware-proxy" }, + ], + }, + { + label: "Site-to-Site Connectivity", + type: "category", + link: { type: "doc", id: "guides/site-to-site-connectivity/index" }, + items: [ { - label: "Using ngrok with", - type: "category", - link: { type: "doc", id: "using-ngrok-with" }, - items: [{ type: "autogenerated", dirName: "using-ngrok-with" }], + type: "autogenerated", + dirName: "guides/site-to-site-connectivity", }, ], }, + { + label: "Developer Preview", + type: "category", + link: { type: "doc", id: "guides/developer-preview/index" }, + items: [{ type: "autogenerated", dirName: "guides/developer-preview" }], + }, + { + label: "Other guides", + type: "category", + link: { type: "doc", id: "guides/other-guides/index" }, + items: [{ type: "autogenerated", dirName: "guides/other-guides" }], + }, + { + label: "Using ngrok with", + type: "category", + link: { type: "doc", id: "using-ngrok-with" }, + items: [{ type: "autogenerated", dirName: "using-ngrok-with" }], + }, { label: "Integrations", type: "category",