# firewallRules (/docs/reference/api/firewall-rules)

> Firewall rules belong to a [network](/docs/reference/api/networks) and are decided on it: reading them takes `compute:networks:read`, changing them `compute:networks:update`. A rule says which traffic is allowed or denied, from where and to which instances, and the `vps.networks` reconciler applies it at the provider as a firewall named `bc-` and the rule's id. A rule that names instances applies to the machines carrying those instances' network tags (`bc-` and 16 hex digits of the sha256 of the instance id), which the reconciler sets on each instance that owns its machine (applying rules first: a tag set later still matches); a rule that names none applies to every instance on the network. A network has at most 100 rules that are not deleted.



Firewall rules belong to a [network](/docs/reference/api/networks) and are decided on it: reading them takes `compute:networks:read`, changing them `compute:networks:update`. A rule says which traffic is allowed or denied, from where and to which instances, and the `vps.networks` reconciler applies it at the provider as a firewall named `bc-` and the rule's id. A rule that names instances applies to the machines carrying those instances' network tags (`bc-` and 16 hex digits of the sha256 of the instance id), which the reconciler sets on each instance that owns its machine (applying rules first: a tag set later still matches); a rule that names none applies to every instance on the network. A network has at most 100 rules that are not deleted.

All 4 methods are served by @better-compute/server 0.3.0.

| Method              | Kind     | Authorization                                 | Phase | Status     |
| ------------------- | -------- | --------------------------------------------- | ----- | ---------- |
| [`create`](#create) | mutation | `compute:networks:update` @ `compute-network` | v1.0  | registered |
| [`list`](#list)     | read     | `compute:networks:read` @ `compute-network`   | v1.0  | registered |
| [`update`](#update) | mutation | `compute:networks:update` @ `compute-network` | v1.0  | registered |
| [`delete`](#delete) | mutation | `compute:networks:update` @ `compute-network` | v1.0  | registered |

## create [#create]

`POST /api/compute/firewallRules/create`

Adds a rule to the network and returns it `pending`.

* `direction` is `ingress` or `egress`. `action` defaults to `allow`, `priority` to 1000 (0 to 65535, lower wins) and `enabled` to `true`; a disabled rule exists at the provider but matches nothing.
* `rules` lists 1 to 20 entries `{ protocol, ports? }` with `protocol` one of `tcp`, `udp`, `icmp` and `all`. `ports` (tcp and udp only) are ports (`"22"`) or ranges (`"8000-8100"`); without them every port is covered.
* An ingress rule must name its `sources`, IPv4 CIDRs, and takes no `destinations`; the whole internet is `0.0.0.0/0`, written out, never implied. An egress rule takes `destinations` (without them, everywhere) and no `sources`. Violations are `INVALID_INPUT`.
* `targets.instanceIds` names instances of the tenant that are on this network and not deleted; any other is `INVALID_INPUT`. Empty targets cover the whole network, except on an adopted network (`networks.adopt`), where a rule must name its instances (`INVALID_INPUT` otherwise, on `update` too): it never covers machines of the VPC that are not the tenant's.
* The name is unique in the network (`CONFLICT`); the name of a deleted rule is free again. A hundred live rules already is `QUOTA_EXCEEDED`. A network being deleted is `INVALID_STATE`.

Publishes `network.rule.ready` once the provider has the rule, or `network.rule.error` with the reason. Decided as `compute:networks:update` on the network.

* **Kind:** mutation
* **Authorization:** `compute:networks:update` @ `compute-network`
* **Module:** `vps`
* **Phase:** v1.0 (registered)

**Input**

| Field                 | Type                               | Required | Constraints                                                        |
| --------------------- | ---------------------------------- | -------- | ------------------------------------------------------------------ |
| `tenantId`            | string                             | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`         |
| `networkId`           | string                             | yes      | at most 56 characters; matches `^net_[0-9a-hjkmnp-tv-z]{26,52}$`   |
| `name`                | string                             | yes      | at most 42 characters; matches `^[a-z]([-a-z0-9]{0,40}[a-z0-9])?$` |
| `direction`           | one of `ingress`, `egress`         | yes      |                                                                    |
| `action`              | one of `allow`, `deny`             |          | default `"allow"`                                                  |
| `priority`            | integer                            |          | 0-65535; default `1000`                                            |
| `rules`               | list of object                     | yes      | 1-20 items                                                         |
| `rules[].protocol`    | one of `tcp`, `udp`, `icmp`, `all` | yes      |                                                                    |
| `rules[].ports`       | list of string                     |          | 0-50 items                                                         |
| `sources`             | list of string                     |          | 0-256 items                                                        |
| `destinations`        | list of string                     |          | 0-256 items                                                        |
| `targets`             | object                             |          |                                                                    |
| `targets.instanceIds` | list of string                     |          | 0-64 items                                                         |
| `enabled`             | boolean                            |          | default `true`                                                     |

## list [#list]

`POST /api/compute/firewallRules/list`

Returns the network's rules that are not deleted, sorted by name, with their state (`pending`, `ready`, `deleting`, `error`).

* **Kind:** read
* **Authorization:** `compute:networks:read` @ `compute-network`
* **Module:** `vps`
* **Phase:** v1.0 (registered)

**Input**

| Field       | Type   | Required | Constraints                                                      |
| ----------- | ------ | -------- | ---------------------------------------------------------------- |
| `tenantId`  | string | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`       |
| `networkId` | string | yes      | at most 56 characters; matches `^net_[0-9a-hjkmnp-tv-z]{26,52}$` |

## update [#update]

`POST /api/compute/firewallRules/update`

Changes the given fields of a rule (`direction`, `action`, `priority`, `rules`, `sources`, `destinations`, `targets`, `enabled`; the name never changes), checks the result as `create` does, bumps `version`, returns the rule `pending` and wakes the reconciler. An empty `sources` or `destinations` list clears it. A rule that changes direction names its other range list again.

* **Kind:** mutation
* **Authorization:** `compute:networks:update` @ `compute-network`
* **Module:** `vps`
* **Phase:** v1.0 (registered)

**Input**

| Field                 | Type                               | Required | Constraints                                                      |
| --------------------- | ---------------------------------- | -------- | ---------------------------------------------------------------- |
| `tenantId`            | string                             | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`       |
| `networkId`           | string                             | yes      | at most 56 characters; matches `^net_[0-9a-hjkmnp-tv-z]{26,52}$` |
| `ruleId`              | string                             | yes      | at most 56 characters; matches `^fwr_[0-9a-hjkmnp-tv-z]{26,52}$` |
| `direction`           | one of `ingress`, `egress`         |          |                                                                  |
| `action`              | one of `allow`, `deny`             |          | default `"allow"`                                                |
| `priority`            | integer                            |          | 0-65535; default `1000`                                          |
| `rules`               | list of object                     |          | 1-20 items                                                       |
| `rules[].protocol`    | one of `tcp`, `udp`, `icmp`, `all` | yes      |                                                                  |
| `rules[].ports`       | list of string                     |          | 0-50 items                                                       |
| `sources`             | list of string                     |          | 0-256 items                                                      |
| `destinations`        | list of string                     |          | 0-256 items                                                      |
| `targets`             | object                             |          |                                                                  |
| `targets.instanceIds` | list of string                     |          | 0-64 items                                                       |
| `enabled`             | boolean                            |          | default `true`                                                   |

## delete [#delete]

`POST /api/compute/firewallRules/delete`

Marks the rule for deletion and returns it `deleting` with `version` bumped; the reconciler removes the firewall at the provider. Deleting a rule that is being deleted returns it unchanged.

* **Kind:** mutation
* **Authorization:** `compute:networks:update` @ `compute-network`
* **Module:** `vps`
* **Phase:** v1.0 (registered)

**Input**

| Field       | Type   | Required | Constraints                                                      |
| ----------- | ------ | -------- | ---------------------------------------------------------------- |
| `tenantId`  | string | yes      | at most 128 characters; matches `^[A-Za-z0-9._:-]{1,128}$`       |
| `networkId` | string | yes      | at most 56 characters; matches `^net_[0-9a-hjkmnp-tv-z]{26,52}$` |
| `ruleId`    | string | yes      | at most 56 characters; matches `^fwr_[0-9a-hjkmnp-tv-z]{26,52}$` |
