Skip to content

Commit

Permalink
feat: default enable allowDynamicBackends with better unsupported err…
Browse files Browse the repository at this point in the history
…ors (#995)
  • Loading branch information
guybedford authored Oct 15, 2024
1 parent c5986c2 commit bb858fe
Show file tree
Hide file tree
Showing 20 changed files with 368 additions and 167 deletions.
67 changes: 2 additions & 65 deletions documentation/docs/backend/Backend/Backend.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,9 @@ import {Fiddle} from '@site/src/components/fiddle';

The **`Backend` constructor** lets you dynamically create new [Fastly Backends](https://developer.fastly.com/reference/api/services/backend/) for your Fastly Compute service.

Dynamically creating new [Fastly Backends](https://developer.fastly.com/reference/api/services/backend/) is disabled by default for Fastly Services. Please contact [Fastly Support](https://support.fastly.com/hc/requests/new?ticket_form_id=360000269711) to request the feature be enabled on the Fastly Services which require Dynamic Backends.
>**Note**: Dynamic backends are by default disabled at the Fastly service level. Contact [Fastly Support](https://support.fastly.com/hc/en-us/requests/new?ticket_form_id=360000269711) to request dynamic backends on Fastly Services.
By default, Dynamic Backends are disabled within a JavaScript application as it can be a potential avenue for third-party JavaScript code to send requests, potentially including sensitive/secret data, off to destinations that the JavaScript project was not intending, which could be a security issue.

To enable Dynamic Backends the application will need to explicitly allow Dynamic Backends via:

```js
import { allowDynamicBackends } from "fastly:experimental";
allowDynamicBackends(true);
```

**Note**: Backend constructors can only be used when processing requests, not during build-time initialization.
To disable the usage of dynamic backends, see [enforceExplicitBackends](../enforceExplicitBackends.mdx).

## Syntax

Expand Down Expand Up @@ -122,58 +113,8 @@ A new `Backend` object.

## Examples

In this example an implicit Dynamic Backend is created when making the fetch request to <https://www.fastly.com/> and the response is then returned to the client.
<Fiddle config={{
"type": "javascript",
"title": "Implicit Dynamic Backend Example",
"origins": [
"https://http-me.glitch.me"
],
"src": {
"deps": "{\n \"@fastly/js-compute\": \"^1.0.1\"\n}",
"main": `
/// <reference types="@fastly/js-compute" />
import { allowDynamicBackends } from "fastly:experimental";
allowDynamicBackends(true);
async function app() {
// For any request, return the fastly homepage -- without defining a backend!
return fetch('https://www.fastly.com/');
}
addEventListener("fetch", event => event.respondWith(app(event)));
`
},
"requests": [
{
"enableCluster": true,
"enableShield": false,
"enableWAF": false,
"method": "GET",
"path": "/status=200",
"useFreshCache": false,
"followRedirects": false,
"tests": "",
"delay": 0
}
],
"srcVersion": 1
}}>

```js
/// <reference types="@fastly/js-compute" />
import { allowDynamicBackends } from "fastly:experimental";
allowDynamicBackends(true);
async function app() {
// For any request, return the fastly homepage -- without defining a backend!
return fetch('https://www.fastly.com/');
}
addEventListener("fetch", event => event.respondWith(app(event)));
```

</Fiddle>

In this example an explicit Dynamic Backend is created and supplied to the fetch request, the response is then returned to the client.


<Fiddle config={{
"type": "javascript",
"title": "Explicit Dynamic Backend Example",
Expand All @@ -184,9 +125,7 @@ In this example an explicit Dynamic Backend is created and supplied to the fetch
"deps": "{\n \"@fastly/js-compute\": \"^1.0.1\"\n}",
"main": `
/// <reference types="@fastly/js-compute" />
import { allowDynamicBackends } from "fastly:experimental";
import { Backend } from "fastly:backend";
allowDynamicBackends(true);
async function app() {
// For any request, return the fastly homepage -- without defining a backend!
const backend = new Backend({
Expand Down Expand Up @@ -225,9 +164,7 @@ addEventListener("fetch", event => event.respondWith(app(event)));

```js
/// <reference types="@fastly/js-compute" />
import { allowDynamicBackends } from "fastly:experimental";
import { Backend } from "fastly:backend";
allowDynamicBackends(true);
async function app() {
// For any request, return the fastly homepage -- without defining a backend!
const backend = new Backend({
Expand Down
76 changes: 76 additions & 0 deletions documentation/docs/backend/Backend/prototype/name.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
hide_title: false
hide_table_of_contents: false
pagination_next: null
pagination_prev: null
---
import {Fiddle} from '@site/src/components/fiddle';

# name

The read-only **`name`** property of the backend returns the backend name string.

## Value

A `string`.

## Description

Provides the name of the backend.

## Examples

### Using name

The following example logs the string value of a [Backend](../Backend.mdx) object:

<Fiddle config={{
"type": "javascript",
"title": "Backend.prototype.name Example",
"origins": [
"https://http-me.glitch.me"
],
"src": {
"deps": "{\n \"@fastly/js-compute\": \"^1.0.1\"\n}",
"main": `
/// <reference types=\"@fastly/js-compute\" />
import { Backend } from "fastly:backend";
async function app() {
const backend = new Backend({
name: "fastly",
target: "fastly.com",
});
console.log(backend.name); // "fastly"
}
addEventListener("fetch", event => event.respondWith(app(event)));
`
},
"requests": [
{
"enableCluster": true,
"enableShield": false,
"enableWAF": false,
"method": "GET",
"path": "/status=200",
"useFreshCache": false,
"followRedirects": false,
"tests": "",
"delay": 0
}
],
"srcVersion": 1
}}>

```js
import { Backend } from "fastly:backend";
async function app() {
const backend = new Backend({
name: "fastly",
target: "fastly.com",
});
console.log(backend.name); // "fastly"
}
addEventListener("fetch", event => event.respondWith(app(event)));
```

</Fiddle>
6 changes: 6 additions & 0 deletions documentation/docs/backend/Backend/prototype/toName.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ pagination_prev: null

# Backend.prototype.toName()

:::info

This method is deprecated, use [`Backend.prototype.name`](./name.mdx) instead.

:::

The **`toName()`** method returns the name associated with the `Backend` instance.

## Syntax
Expand Down
6 changes: 6 additions & 0 deletions documentation/docs/backend/Backend/prototype/toString.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import {Fiddle} from '@site/src/components/fiddle';

# toString

:::info

This method is deprecated, use [`Backend.prototype.name`](./name.mdx) instead.

:::

The **`toString()`** method returns a string representing the specified Backend value.

## Syntax
Expand Down
38 changes: 38 additions & 0 deletions documentation/docs/backend/allowDynamicBackends.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
hide_title: false
hide_table_of_contents: false
pagination_next: null
pagination_prev: null
---
import {Fiddle} from '@site/src/components/fiddle';

# allowDynamicBackends

:::info

This method is deprecated, and dynamic backends are now always supported when enabled at the service level. See [`enforceExplicitBackends`](./enforceExplicitBackends.mdx) instead.

:::

The **`allowDynamicBackends()`** function is used to control whether or not Dynamic Backends should be allowed within this Fastly Compute Service.

By default, Dynamic Backends are enabled, but can be a potential security concern since third-party JavaScript code may send arbitrary requests, potentially including sensitive/secret data, off to destinations that the JavaScript project was not intending.

Using `allowDynamicBackends(false)` this security property can be restored to only use explicit backend definitions.

>**Note**: By default, while dynamic backends are allowed in the SDK, they are by default disabled at the Fastly service level.
## Syntax

```js
allowDynamicBackends(enabledOrConfig)
```

### Parameters

- `enabled` _: boolean_
- Whether or not to allow Dynamic Backends

### Return value

`undefined`.
43 changes: 43 additions & 0 deletions documentation/docs/backend/enforceExplicitBackends.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
hide_title: false
hide_table_of_contents: false
pagination_next: null
pagination_prev: null
---

# enforceExplicitBackends

Call this function to enforce the security property of explicitly-defined backends, even when dynamic backends are enabled at
the Fastly service level.

By default, if dynamic backends are supported for the Fastly service, they will be automatically used when creating a new
`fetch()` request. This default behaviour for dynamic backends can be a potential security concern since third-party JavaScript
code may send arbitrary requests, including sensitive/secret data, off to destinations that the JavaScript project was not
intending.

When calling this function, an optional default backend name can be provided.

>**Note**: This is a separate option to the service-level dynamic backend support for Fastly services, which is by deault disabled for Fastly services.
The **`enforceExplicitBackends()`** function is used to control whether or not Dynamic Backends should be allowed within this Fastly Compute Service.

By default, Dynamic Backends are enabled, but can be a potential security concern since third-party JavaScript code may send arbitrary requests, potentially including sensitive/secret data, off to destinations that the JavaScript project was not intending.

Using `allowDynamicBackends(false)` this security property can be restored to only use explicit backend definitions.

>**Note**: Dynamic Backends are disabled by default for Fastly Services. Please contact [Fastly Support](https://support.fastly.com/hc/requests/new?ticket_form_id=360000269711) to request the feature be enabled or disabled on Fastly Services.
## Syntax

```js
enforceExplicitBackends(defaultBackend?)
```
### Parameters
- `defaultBackend` _: string_ _**optional**_
- An optional default backend string name to use in `fetch()` requests.
### Return value
`undefined`.
20 changes: 20 additions & 0 deletions documentation/docs/globals/fetch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ not_ reject on HTTP errors (`404`, etc.). Instead, a
> **Note:** The `fetch()` method's parameters are identical to
> those of the `Request()` constructor.
## Explicit Backends

Internally, Fastly uses named backends to handle fetch requests, which need to be explicitly defined to enable custom HTTP origins to be fetched by the service.

This `backend` option is then a special Fastly-specific fetch option that is provided to the `fetch()` call:

```js
fetch('https://origin.com/path', { backend: 'origin' });
```

Backends are configured using the Fastly service backend configuration, see the [Backend documentation](https://developer.fastly.com/reference/api/services/backend/) for more information.

## Dynamic Backends

Dynamic backends are a compute feature that allow services to define backends for themselves. This is a service-level Fastly feature that must be enabled through [Fastly Support](https://support.fastly.com/hc/en-us/requests/new?ticket_form_id=360000269711).

When dynamic backends are enabled at the service level, the explicit `backend` option is no longer required for `fetch()` requests, and will instead be automatically created.

In addition, custom backend confiuration options can then also be provided through the [`Backend()`](../fastly:backend/Backend/Backend.mdx) constructor.

## Syntax

```js
Expand Down
19 changes: 17 additions & 2 deletions integration-tests/js-compute/fixtures/app/src/dynamic-backend.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/// <reference path="../../../../../types/index.d.ts" />
import { Backend, setDefaultDynamicBackendConfig } from 'fastly:backend';
import { CacheOverride } from 'fastly:cache-override';
import {
Backend,
setDefaultDynamicBackendConfig,
enforceExplicitBackends,
} from 'fastly:backend';
import { allowDynamicBackends } from 'fastly:experimental';
import { CacheOverride } from 'fastly:cache-override';
import {
assert,
assertDoesNotThrow,
Expand Down Expand Up @@ -55,6 +59,10 @@ routes.set('/backend/timeout', async () => {
allowDynamicBackends(true);
await assertResolves(() => fetch('https://http-me.glitch.me/headers'));
await assertResolves(() => fetch('https://www.fastly.com'));
enforceExplicitBackends();
await assertRejects(() => fetch('https://www.fastly.com'));
enforceExplicitBackends('TheOrigin');
await assertResolves(() => fetch('https://www.fastly.com'));
});
routes.set(
'/implicit-dynamic-backend/dynamic-backends-enabled-called-twice',
Expand Down Expand Up @@ -225,6 +233,7 @@ routes.set('/backend/timeout', async () => {
actual = Reflect.ownKeys(Backend.prototype);
expected = [
'constructor',
'name',
'isDynamic',
'target',
'hostOverride',
Expand Down Expand Up @@ -2432,6 +2441,9 @@ routes.set('/backend/timeout', async () => {
{
const backend = createValidFastlyBackend() ?? validFastlyBackend;
strictEqual(backend.isDynamic, true, 'isDymamic');
strictEqual(backend.name, 'fastly');
strictEqual(backend.toString(), 'fastly');
strictEqual(backend.toName(), 'fastly');
strictEqual(backend.target, 'www.fastly.com', 'target');
strictEqual(backend.hostOverride, 'www.fastly.com', 'override');
strictEqual(backend.port, 443, 'port');
Expand Down Expand Up @@ -2466,6 +2478,9 @@ routes.set('/backend/timeout', async () => {
{
const backend = createValidHttpMeBackend() ?? validHttpMeBackend;
strictEqual(backend.isDynamic, true, 'isDynamic');
strictEqual(backend.name, 'http-me');
strictEqual(backend.toString(), 'http-me');
strictEqual(backend.toName(), 'http-me');
strictEqual(backend.target, 'http-me.glitch.me', 'target');
strictEqual(backend.hostOverride, 'http-me.glitch.me', 'hostOverride');
strictEqual(backend.port, 443, 'port');
Expand Down
Loading

0 comments on commit bb858fe

Please sign in to comment.