@takodotid/circuit 0.43.1 → 1.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -37
- package/package.json +21 -58
- package/src/checks/across.ts +402 -0
- package/src/checks/built-in.ts +256 -0
- package/src/checks/device.ts +436 -0
- package/src/checks/index.ts +53 -0
- package/src/cli/advisories.ts +108 -0
- package/src/cli/app.ts +71 -0
- package/src/cli/editor-types.generated.ts +30 -0
- package/src/cli/editor-types.ts +69 -0
- package/src/cli/format.ts +124 -0
- package/src/cli/git-hooks.ts +79 -0
- package/src/cli/index.ts +350 -1170
- package/src/cli/migrate.ts +554 -0
- package/src/cli/project-commands.ts +656 -0
- package/src/cli/releases.ts +374 -0
- package/src/cli/remember.ts +339 -0
- package/src/cli/rename.ts +27 -33
- package/src/cli/secrets-password.ts +60 -0
- package/src/cli/secrets.ts +258 -0
- package/src/cli/setup.ts +300 -0
- package/src/cli/signing.ts +23 -0
- package/src/cli/text-editor.ts +268 -0
- package/src/cli/ui.ts +298 -0
- package/src/cli/version.ts +2 -0
- package/src/cli/versions.ts +158 -0
- package/src/config/address.ts +102 -0
- package/src/config/circuit.d.ts +30 -0
- package/src/config/common.ts +65 -0
- package/src/config/communities.ts +479 -0
- package/src/config/define.ts +684 -0
- package/src/config/device.ts +164 -0
- package/src/config/firewall.ts +150 -0
- package/src/config/index.ts +22 -0
- package/src/{schema → config}/interfaces.ts +121 -85
- package/src/config/keys.ts +434 -0
- package/src/config/management.ts +61 -0
- package/src/config/merge.ts +335 -0
- package/src/config/models.ts +70 -0
- package/src/config/monitoring.ts +64 -0
- package/src/config/network.ts +180 -0
- package/src/config/presets.ts +149 -0
- package/src/config/routing.ts +401 -0
- package/src/config/services.ts +51 -0
- package/src/config/switching.ts +84 -0
- package/src/config/system.ts +103 -0
- package/src/{schema → config}/time-zones.ts +1 -1
- package/src/core/address.ts +1 -1
- package/src/core/cabling.ts +8 -43
- package/src/core/graph.ts +40 -0
- package/src/{integrations → core}/registries.ts +5 -3
- package/src/core/secrets-file.ts +539 -0
- package/src/core/secrets.ts +83 -64
- package/src/core/topology.ts +103 -146
- package/src/core/utils.ts +12 -1
- package/src/model.ts +83 -0
- package/src/platforms/derive.ts +64 -37
- package/src/platforms/finding.ts +9 -0
- package/src/platforms/fortios/firewall.ts +76 -64
- package/src/platforms/fortios/index.ts +189 -125
- package/src/platforms/fortios/names.ts +51 -18
- package/src/platforms/fortios/render.ts +69 -62
- package/src/platforms/fortios/routing.ts +89 -58
- package/src/platforms/fortios/vdoms.ts +47 -16
- package/src/platforms/junos/TRAPS.md +2 -2
- package/src/platforms/junos/bgp.ts +63 -42
- package/src/platforms/junos/index.ts +122 -89
- package/src/platforms/junos/render.ts +139 -104
- package/src/platforms/platform.ts +10 -8
- package/src/platforms/raisecom-ros/TRAPS.md +1 -1
- package/src/platforms/raisecom-ros/index.ts +89 -70
- package/src/platforms/raisecom-ros/render.ts +49 -45
- package/src/platforms/routeros/TRAPS.md +3 -3
- package/src/platforms/routeros/index.ts +121 -60
- package/src/platforms/routeros/render.ts +214 -195
- package/src/platforms/vrp/TRAPS.md +1 -1
- package/src/platforms/vrp/index.ts +74 -50
- package/src/platforms/vrp/render.ts +67 -56
- package/src/project/project.ts +725 -0
- package/src/studio/app/env.d.ts +9 -0
- package/src/studio/app/index.html +18 -0
- package/src/studio/app/src/App.vue +95 -0
- package/src/studio/app/src/components/AddressesView.vue +38 -0
- package/src/studio/app/src/components/CablesView.vue +29 -0
- package/src/studio/app/src/components/CompareView.vue +160 -0
- package/src/studio/app/src/components/DataTable.vue +49 -0
- package/src/studio/app/src/components/DeviceView.vue +237 -0
- package/src/studio/app/src/components/DevicesView.vue +32 -0
- package/src/studio/app/src/components/Faceplate.vue +75 -0
- package/src/studio/app/src/components/GraphView.vue +282 -0
- package/src/studio/app/src/components/LineDiff.vue +24 -0
- package/src/studio/app/src/components/ProblemsView.vue +42 -0
- package/src/studio/app/src/components/SearchView.vue +72 -0
- package/src/studio/app/src/components/SecretsView.vue +112 -0
- package/src/studio/app/src/components/SessionsView.vue +35 -0
- package/src/studio/app/src/components/Settings.vue +95 -0
- package/src/studio/app/src/components/ToolsView.vue +118 -0
- package/src/studio/app/src/components/VlansView.vue +50 -0
- package/src/studio/app/src/lib/csv.ts +19 -0
- package/src/studio/{public/diff.js → app/src/lib/diff.ts} +40 -35
- package/src/studio/app/src/lib/format.ts +38 -0
- package/src/studio/app/src/lib/net.ts +68 -0
- package/src/studio/app/src/lib/secrets-crypto.ts +35 -0
- package/src/studio/app/src/lib/store.ts +71 -0
- package/src/studio/app/src/lib/tools.ts +217 -0
- package/src/studio/app/src/main.ts +9 -0
- package/src/studio/{public → app/src}/style.css +14 -4
- package/src/studio/app/tsconfig.json +17 -0
- package/src/studio/app/vite.config.ts +16 -0
- package/src/studio/assets.generated.ts +3 -0
- package/src/studio/data.ts +96 -188
- package/src/studio/git.ts +27 -43
- package/src/studio/server.ts +196 -107
- package/src/studio/types.ts +141 -0
- package/src/transport/console.ts +3 -3
- package/src/transport/ssh.ts +1 -1
- package/dist/chunks/index-3b343xva.js +0 -177
- package/dist/chunks/index-6wb41q67.js +0 -62
- package/dist/chunks/index-n7w3tg5y.js +0 -149
- package/dist/chunks/index-yzw86rc8.js +0 -921
- package/dist/chunks/new-w3zys5y4.js +0 -172
- package/dist/chunks/server-cxr9ynxc.js +0 -259
- package/dist/cli/index.js +0 -12922
- package/dist/helpers/index.js +0 -881
- package/dist/index.js +0 -28
- package/dist/types/core/address-space.d.ts +0 -62
- package/dist/types/core/address.d.ts +0 -44
- package/dist/types/core/cabling.d.ts +0 -41
- package/dist/types/core/cross-checks.d.ts +0 -28
- package/dist/types/core/define.d.ts +0 -79
- package/dist/types/core/project-files.d.ts +0 -12
- package/dist/types/core/schema-docs.d.ts +0 -25
- package/dist/types/core/secrets.d.ts +0 -62
- package/dist/types/core/topology.d.ts +0 -96
- package/dist/types/core/utils.d.ts +0 -10
- package/dist/types/core/validator.d.ts +0 -23
- package/dist/types/helpers/bgp.d.ts +0 -195
- package/dist/types/helpers/cables.d.ts +0 -69
- package/dist/types/helpers/checks.d.ts +0 -36
- package/dist/types/helpers/exchange.d.ts +0 -55
- package/dist/types/helpers/filters.d.ts +0 -51
- package/dist/types/helpers/index.d.ts +0 -14
- package/dist/types/helpers/route-server.d.ts +0 -52
- package/dist/types/helpers/upstreams.d.ts +0 -192
- package/dist/types/index.d.ts +0 -10
- package/dist/types/integrations/librenms.d.ts +0 -60
- package/dist/types/integrations/netbox.d.ts +0 -89
- package/dist/types/integrations/peeringdb.d.ts +0 -24
- package/dist/types/integrations/prometheus.d.ts +0 -24
- package/dist/types/integrations/registries.d.ts +0 -8
- package/dist/types/platforms/bgp-wait.d.ts +0 -24
- package/dist/types/platforms/catalog.d.ts +0 -109
- package/dist/types/platforms/derive.d.ts +0 -17
- package/dist/types/platforms/fortios/firewall.d.ts +0 -47
- package/dist/types/platforms/fortios/index.d.ts +0 -140
- package/dist/types/platforms/fortios/models.d.ts +0 -14
- package/dist/types/platforms/fortios/names.d.ts +0 -52
- package/dist/types/platforms/fortios/plan.d.ts +0 -114
- package/dist/types/platforms/fortios/render.d.ts +0 -77
- package/dist/types/platforms/fortios/routing.d.ts +0 -56
- package/dist/types/platforms/fortios/tree.d.ts +0 -37
- package/dist/types/platforms/fortios/vdoms.d.ts +0 -50
- package/dist/types/platforms/index.d.ts +0 -13
- package/dist/types/platforms/junos/bgp.d.ts +0 -44
- package/dist/types/platforms/junos/index.d.ts +0 -114
- package/dist/types/platforms/junos/models.d.ts +0 -14
- package/dist/types/platforms/junos/render.d.ts +0 -154
- package/dist/types/platforms/line-diff.d.ts +0 -67
- package/dist/types/platforms/platform.d.ts +0 -135
- package/dist/types/platforms/raisecom-ros/index.d.ts +0 -71
- package/dist/types/platforms/raisecom-ros/models.d.ts +0 -14
- package/dist/types/platforms/raisecom-ros/render.d.ts +0 -41
- package/dist/types/platforms/routeros/export.d.ts +0 -59
- package/dist/types/platforms/routeros/index.d.ts +0 -116
- package/dist/types/platforms/routeros/models.d.ts +0 -18
- package/dist/types/platforms/routeros/plan.d.ts +0 -58
- package/dist/types/platforms/routeros/render.d.ts +0 -250
- package/dist/types/platforms/vrp/index.d.ts +0 -83
- package/dist/types/platforms/vrp/models.d.ts +0 -12
- package/dist/types/platforms/vrp/render.d.ts +0 -96
- package/dist/types/schema/common.d.ts +0 -30
- package/dist/types/schema/device.d.ts +0 -126
- package/dist/types/schema/firewall.d.ts +0 -131
- package/dist/types/schema/index.d.ts +0 -8
- package/dist/types/schema/interfaces.d.ts +0 -205
- package/dist/types/schema/policy.d.ts +0 -107
- package/dist/types/schema/routing.d.ts +0 -161
- package/dist/types/schema/system.d.ts +0 -198
- package/dist/types/schema/time-zones.d.ts +0 -2
- package/dist/types/transport/console.d.ts +0 -115
- package/dist/types/transport/path-check.d.ts +0 -32
- package/dist/types/transport/ssh.d.ts +0 -27
- package/src/cli/graph-format.ts +0 -91
- package/src/cli/new.ts +0 -234
- package/src/core/address-space.ts +0 -320
- package/src/core/cross-checks.ts +0 -369
- package/src/core/define.ts +0 -124
- package/src/core/project-files.ts +0 -35
- package/src/core/schema-docs.ts +0 -174
- package/src/core/validator.ts +0 -508
- package/src/helpers/bgp.ts +0 -473
- package/src/helpers/cables.ts +0 -74
- package/src/helpers/checks.ts +0 -201
- package/src/helpers/exchange.ts +0 -123
- package/src/helpers/filters.ts +0 -107
- package/src/helpers/index.ts +0 -25
- package/src/helpers/route-server.ts +0 -212
- package/src/helpers/upstreams.ts +0 -369
- package/src/index.ts +0 -13
- package/src/integrations/librenms.ts +0 -291
- package/src/integrations/netbox.ts +0 -620
- package/src/integrations/peeringdb.ts +0 -173
- package/src/integrations/prometheus.ts +0 -90
- package/src/schema/common.ts +0 -41
- package/src/schema/device.ts +0 -145
- package/src/schema/firewall.ts +0 -140
- package/src/schema/index.ts +0 -8
- package/src/schema/policy.ts +0 -115
- package/src/schema/routing.ts +0 -173
- package/src/schema/system.ts +0 -203
- package/src/studio/public/app.js +0 -186
- package/src/studio/public/compare.js +0 -250
- package/src/studio/public/dom.js +0 -138
- package/src/studio/public/evaluate.js +0 -687
- package/src/studio/public/export.js +0 -130
- package/src/studio/public/graph.js +0 -1541
- package/src/studio/public/index.html +0 -83
- package/src/studio/public/net.js +0 -134
- package/src/studio/public/tables.js +0 -1289
- package/src/studio/public/tools.js +0 -610
- package/templates/colocation/checks.ts +0 -53
- package/templates/colocation/circuit.config.ts +0 -9
- package/templates/colocation/edge-01.ts +0 -133
- package/templates/colocation/routing.ts +0 -13
- package/templates/colocation/tenancy.ts +0 -76
- package/templates/colocation/tenants/acme.ts +0 -19
- package/templates/colocation/tenants/index.ts +0 -6
- package/templates/colocation/tor-01.ts +0 -33
- package/templates/edge-router/checks.ts +0 -20
- package/templates/edge-router/circuit.config.ts +0 -8
- package/templates/edge-router/edge-01.ts +0 -110
- package/templates/edge-router/routing.ts +0 -13
- package/templates/project/AGENTS.md +0 -51
- package/templates/project/CLAUDE.md +0 -1
- package/templates/project/README.md +0 -16
- package/templates/project/gitignore +0 -5
- package/templates/project/tsconfig.json +0 -13
- package/templates/single-site/checks.ts +0 -26
- package/templates/single-site/circuit.config.ts +0 -8
- package/templates/single-site/router.ts +0 -86
- package/templates/single-site/site.ts +0 -18
- package/templates/single-site/switch.ts +0 -34
- /package/src/studio/{public → app/public}/favicon.svg +0 -0
- /package/src/studio/{public → app/public}/special-gothic-latin-ext.woff2 +0 -0
- /package/src/studio/{public → app/public}/special-gothic-latin.woff2 +0 -0
- /package/src/studio/{public → app/public}/special-gothic-license.txt +0 -0
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
// Keeps a network's exchange presence at PeeringDB in step with the config. Each interface with an `exchange` naming a `peeringdb_ixlan` is one record.
|
|
2
|
-
//
|
|
3
|
-
// Only globally reachable addresses are published: an exchange reached over a tunnel often lands on private or shared space, and publishing it would point others at a dead end. A record the config does not hold is reported, never deleted, and `operational` is never changed, since leaving an exchange is a decision made outside the config.
|
|
4
|
-
|
|
5
|
-
import { Address } from "../core/address";
|
|
6
|
-
import type { Network } from "../core/define";
|
|
7
|
-
import { Secrets } from "../core/secrets";
|
|
8
|
-
import type { Device, Interface } from "../schema";
|
|
9
|
-
|
|
10
|
-
/** A network's presence at one exchange LAN, as PeeringDB holds it. */
|
|
11
|
-
type NetIxLan = {
|
|
12
|
-
id: number;
|
|
13
|
-
net_id: number;
|
|
14
|
-
ixlan_id: number;
|
|
15
|
-
name: string;
|
|
16
|
-
speed: number;
|
|
17
|
-
ipaddr4: string | null;
|
|
18
|
-
ipaddr6: string | null;
|
|
19
|
-
is_rs_peer: boolean;
|
|
20
|
-
operational: boolean;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/** One record as the config describes it. */
|
|
24
|
-
type Wanted = {
|
|
25
|
-
name: string;
|
|
26
|
-
ixlan_id: number;
|
|
27
|
-
speed: number;
|
|
28
|
-
ipaddr4: string | null;
|
|
29
|
-
ipaddr6: string | null;
|
|
30
|
-
is_rs_peer: boolean;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
/** A change to send. `id` is set when the record exists and is updated in place. */
|
|
34
|
-
export type PeeringDbChange = {
|
|
35
|
-
summary: string;
|
|
36
|
-
id?: number;
|
|
37
|
-
body: Record<string, unknown>;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export type PeeringDbPlan = {
|
|
41
|
-
changes: PeeringDbChange[];
|
|
42
|
-
/** Records PeeringDB holds that the config does not. */
|
|
43
|
-
unknown: string[];
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
type AnyInterface = Interface<string, string>;
|
|
47
|
-
|
|
48
|
-
export class PeeringDb {
|
|
49
|
-
private static readonly API = "https://www.peeringdb.com/api";
|
|
50
|
-
|
|
51
|
-
/** What would change at PeeringDB. Reads the public API; needs no key. */
|
|
52
|
-
static async plan(network: Network): Promise<PeeringDbPlan> {
|
|
53
|
-
if (!network.asn) throw new Error("the network declares no asn");
|
|
54
|
-
|
|
55
|
-
const response = await fetch(`${PeeringDb.API}/netixlan?asn=${network.asn}`, {
|
|
56
|
-
headers: { Accept: "application/json" },
|
|
57
|
-
signal: AbortSignal.timeout(30_000),
|
|
58
|
-
});
|
|
59
|
-
if (!response.ok) throw new Error(`PeeringDB answered ${response.status}`);
|
|
60
|
-
|
|
61
|
-
const existing = ((await response.json()) as { data: NetIxLan[] }).data;
|
|
62
|
-
const desired = PeeringDb.wanted(network);
|
|
63
|
-
|
|
64
|
-
// The record that owns every presence. Taken from an existing one, since the API has no other lookup by ASN here.
|
|
65
|
-
const netId = existing[0]?.net_id;
|
|
66
|
-
const changes: PeeringDbChange[] = [];
|
|
67
|
-
|
|
68
|
-
for (const record of desired) {
|
|
69
|
-
const current = existing.find((candidate) => candidate.ixlan_id === record.ixlan_id);
|
|
70
|
-
|
|
71
|
-
const body = {
|
|
72
|
-
net_id: netId,
|
|
73
|
-
ixlan_id: record.ixlan_id,
|
|
74
|
-
asn: network.asn,
|
|
75
|
-
speed: record.speed,
|
|
76
|
-
ipaddr4: record.ipaddr4,
|
|
77
|
-
ipaddr6: record.ipaddr6,
|
|
78
|
-
is_rs_peer: record.is_rs_peer,
|
|
79
|
-
operational: current?.operational ?? true,
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
if (!current) {
|
|
83
|
-
changes.push({ summary: `+ ${record.name}: ${record.ipaddr4}, ${record.ipaddr6}, ${record.speed} Mbit/s`, body });
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const differs =
|
|
88
|
-
current.ipaddr4 !== record.ipaddr4 ||
|
|
89
|
-
current.ipaddr6 !== record.ipaddr6 ||
|
|
90
|
-
current.speed !== record.speed ||
|
|
91
|
-
current.is_rs_peer !== record.is_rs_peer;
|
|
92
|
-
|
|
93
|
-
if (differs) {
|
|
94
|
-
const before = `${current.ipaddr4}, ${current.ipaddr6}, ${current.speed} Mbit/s, route server ${current.is_rs_peer}`;
|
|
95
|
-
const after = `${record.ipaddr4}, ${record.ipaddr6}, ${record.speed} Mbit/s, route server ${record.is_rs_peer}`;
|
|
96
|
-
changes.push({ summary: `~ ${record.name}: ${before} to ${after}`, id: current.id, body });
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const unknown = existing
|
|
101
|
-
.filter((record) => !desired.some((candidate) => candidate.ixlan_id === record.ixlan_id))
|
|
102
|
-
.map((record) => record.name);
|
|
103
|
-
|
|
104
|
-
if (changes.some((change) => !change.id) && !netId) {
|
|
105
|
-
throw new Error("PeeringDB holds no presence for this network yet, so its record id is unknown; add the first one by hand");
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return { changes, unknown };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/** Send the changes, with the network's API key. */
|
|
112
|
-
static async send(network: Network, changes: PeeringDbChange[]): Promise<void> {
|
|
113
|
-
if (!network.peeringdb) throw new Error("the network declares no peeringdb api_key");
|
|
114
|
-
const apiKey = Secrets.reveal(network.peeringdb.api_key);
|
|
115
|
-
|
|
116
|
-
for (const change of changes) {
|
|
117
|
-
const response = await fetch(`${PeeringDb.API}/netixlan${change.id ? `/${change.id}` : ""}`, {
|
|
118
|
-
method: change.id ? "PUT" : "POST",
|
|
119
|
-
headers: { Authorization: `Api-Key ${apiKey}`, "Content-Type": "application/json" },
|
|
120
|
-
body: JSON.stringify(change.body),
|
|
121
|
-
signal: AbortSignal.timeout(30_000),
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
if (!response.ok) {
|
|
125
|
-
const reason = (await response.text()).slice(0, 300);
|
|
126
|
-
throw new Error(`${change.summary}: PeeringDB answered ${response.status} ${reason}`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
console.log(` sent ${change.summary}`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
private static addressesOf(iface: AnyInterface): string[] {
|
|
134
|
-
return (iface.addresses ?? []).map((entry) => (typeof entry === "string" ? entry : entry.address));
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/** Whether the device peers with a route server on this interface's subnets. */
|
|
138
|
-
private static peersWithRouteServer(device: Device, iface: AnyInterface): boolean {
|
|
139
|
-
const bgp = device.routing?.bgp;
|
|
140
|
-
const subnets = PeeringDb.addressesOf(iface);
|
|
141
|
-
|
|
142
|
-
return Object.values(bgp?.neighbors ?? {}).some((neighbor) => {
|
|
143
|
-
const group = neighbor.group ? bgp?.groups?.[neighbor.group] : undefined;
|
|
144
|
-
const role = neighbor.role ?? group?.role;
|
|
145
|
-
return role === "rs" && subnets.some((subnet) => Address.contains(subnet, neighbor.address));
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** Every exchange presence the config declares with a PeeringDB exchange LAN. */
|
|
150
|
-
private static wanted(network: Network): Wanted[] {
|
|
151
|
-
const records: Wanted[] = [];
|
|
152
|
-
|
|
153
|
-
for (const device of network.devices) {
|
|
154
|
-
for (const iface of Object.values(device.interfaces ?? {})) {
|
|
155
|
-
const exchange = iface.exchange;
|
|
156
|
-
if (!exchange?.peeringdb_ixlan) continue;
|
|
157
|
-
|
|
158
|
-
const published = PeeringDb.addressesOf(iface).map(Address.host).filter(Address.isGlobal);
|
|
159
|
-
|
|
160
|
-
records.push({
|
|
161
|
-
name: exchange.name,
|
|
162
|
-
ixlan_id: exchange.peeringdb_ixlan,
|
|
163
|
-
speed: exchange.speed,
|
|
164
|
-
ipaddr4: published.find((address) => Address.family(address) === "ipv4") ?? null,
|
|
165
|
-
ipaddr6: published.find((address) => Address.family(address) === "ipv6") ?? null,
|
|
166
|
-
is_rs_peer: PeeringDb.peersWithRouteServer(device, iface),
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return records;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
// Prometheus targets for snmp_exporter, in its file-based discovery format, and the `auths` section of its config: one auth per device, named after it, so each device is asked with its own credentials.
|
|
2
|
-
//
|
|
3
|
-
// The auths hold no secret. A password is written as `${NAME}`, the name of its secret, and snmp_exporter reads it from its environment when started with `--config.expand-environment-variables`.
|
|
4
|
-
|
|
5
|
-
import { Document } from "yaml";
|
|
6
|
-
import type { Network } from "../core/define";
|
|
7
|
-
import type { Device, Secret } from "../schema";
|
|
8
|
-
|
|
9
|
-
export type PrometheusTarget = { targets: string[]; labels: Record<string, string> };
|
|
10
|
-
|
|
11
|
-
/** One auth in snmp_exporter's config. */
|
|
12
|
-
type SnmpExporterAuth =
|
|
13
|
-
| {
|
|
14
|
-
version: 3;
|
|
15
|
-
username: string;
|
|
16
|
-
security_level: "authPriv";
|
|
17
|
-
password: string;
|
|
18
|
-
auth_protocol: string;
|
|
19
|
-
priv_protocol: string;
|
|
20
|
-
priv_password: string;
|
|
21
|
-
}
|
|
22
|
-
| { version: 2; community: string };
|
|
23
|
-
|
|
24
|
-
export class Prometheus {
|
|
25
|
-
/** snmp_exporter's names for the algorithms. */
|
|
26
|
-
private static readonly AUTH = { sha1: "SHA", sha256: "SHA256" } as const;
|
|
27
|
-
private static readonly PRIVACY = { aes128: "AES", des: "DES" } as const;
|
|
28
|
-
|
|
29
|
-
private static readonly AUTHS_HEADER =
|
|
30
|
-
" Written by `circuit prometheus --auths`. Load it beside snmp.yml, with --config.expand-environment-variables.";
|
|
31
|
-
|
|
32
|
-
/** The targets, and the devices left out because their config turns SNMP off. */
|
|
33
|
-
static targets(network: Network): { targets: PrometheusTarget[]; withoutSnmp: Device[] } {
|
|
34
|
-
return {
|
|
35
|
-
targets: network.devices
|
|
36
|
-
.filter((device) => device.management?.snmp && device.connection.host)
|
|
37
|
-
.map((device) => ({
|
|
38
|
-
targets: [device.connection.host!],
|
|
39
|
-
// `__param_auth` picks the device's own auth in snmp_exporter.
|
|
40
|
-
labels: { device: device.name, platform: device.platform, model: device.model, __param_auth: device.name },
|
|
41
|
-
})),
|
|
42
|
-
withoutSnmp: network.devices.filter((device) => !device.management?.snmp),
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** The `auths` section, as YAML, and what the operator must still fill in by hand. */
|
|
47
|
-
static snmpExporterAuths(network: Network): { yaml: string; notes: string[] } {
|
|
48
|
-
const notes: string[] = [];
|
|
49
|
-
const auths: Record<string, SnmpExporterAuth> = {};
|
|
50
|
-
|
|
51
|
-
for (const device of network.devices) {
|
|
52
|
-
const snmp = device.management?.snmp;
|
|
53
|
-
if (!snmp) continue;
|
|
54
|
-
|
|
55
|
-
const [name, user] = Object.entries(snmp.users ?? {})[0] ?? [];
|
|
56
|
-
|
|
57
|
-
if (name && user) {
|
|
58
|
-
auths[device.name] = {
|
|
59
|
-
version: 3,
|
|
60
|
-
username: name,
|
|
61
|
-
security_level: "authPriv",
|
|
62
|
-
password: Prometheus.fromEnvironment(user.auth_password, notes, `${device.name}'s SNMP password`),
|
|
63
|
-
auth_protocol: Prometheus.AUTH[user.auth],
|
|
64
|
-
priv_protocol: Prometheus.PRIVACY[user.privacy],
|
|
65
|
-
priv_password: Prometheus.fromEnvironment(user.privacy_password, notes, `${device.name}'s SNMP privacy password`),
|
|
66
|
-
};
|
|
67
|
-
} else {
|
|
68
|
-
// snmp_exporter reads no community from the environment, and Circuit never writes a secret's value.
|
|
69
|
-
auths[device.name] = { version: 2, community: "FILL_IN" };
|
|
70
|
-
notes.push(
|
|
71
|
-
`${device.name} has only an SNMP version 2c community, which snmp_exporter cannot read from its environment; write it in place of FILL_IN, or give the device a version 3 user`
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// YAML 1.1 rules quote words such as `yes` and `on`, which older YAML readers take as true.
|
|
77
|
-
const document = new Document({ auths }, { version: "1.1" });
|
|
78
|
-
document.contents!.commentBefore = Prometheus.AUTHS_HEADER;
|
|
79
|
-
|
|
80
|
-
return { yaml: document.toString({ indent: 2 }), notes };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** A password as snmp_exporter reads it from its environment, or a note when the secret is a file, which it cannot read. */
|
|
84
|
-
private static fromEnvironment(secret: Secret, notes: string[], where: string): string {
|
|
85
|
-
if ("secret" in secret) return `\${${secret.secret}}`;
|
|
86
|
-
|
|
87
|
-
notes.push(`${where} is read from a file; write its value in place of FILL_IN`);
|
|
88
|
-
return "FILL_IN";
|
|
89
|
-
}
|
|
90
|
-
}
|
package/src/schema/common.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A value kept out of the repository and resolved only when a device is applied.
|
|
3
|
-
*
|
|
4
|
-
* `secret("NAME")` reads a variable from the environment or `.env` beside the config; a value written as `op://vault/item/field` is read from 1Password. `secretFile("path")` reads a file, relative to the config file, for a value that spans lines such as a private key in PEM. Keep that file out of git.
|
|
5
|
-
*/
|
|
6
|
-
export type Secret =
|
|
7
|
-
| {
|
|
8
|
-
/** Name of the value in the environment or in `.env`. */
|
|
9
|
-
readonly secret: string;
|
|
10
|
-
}
|
|
11
|
-
| {
|
|
12
|
-
/** Path of the file with the value, relative to the config file. */
|
|
13
|
-
readonly secret_file: string;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/** An IPv4 address, four numbers with dots between them, for example `10.0.0.1`. The type checks the shape; `circuit validate` checks each number is 0 to 255. */
|
|
17
|
-
export type IPv4 = `${number}.${number}.${number}.${number}`;
|
|
18
|
-
|
|
19
|
-
/** An IPv6 address, groups with colons between them, for example `2001:db8::1`. The type only checks there is a colon; `circuit validate` checks the rest. */
|
|
20
|
-
export type IPv6 = `${string}:${string}`;
|
|
21
|
-
|
|
22
|
-
/** An address without a length, IPv4 or IPv6, for example `10.0.0.1` or `2001:db8::1`. */
|
|
23
|
-
export type IP = IPv4 | IPv6;
|
|
24
|
-
|
|
25
|
-
/** A network with its length, for example `10.0.0.0/24` or `2001:db8::/32`. */
|
|
26
|
-
export type Prefix = `${IP}/${number}`;
|
|
27
|
-
|
|
28
|
-
/** An interface address with its length, for example `10.0.0.1/24` or `2001:db8::1/64`. */
|
|
29
|
-
export type InterfaceAddress = `${IP}/${number}`;
|
|
30
|
-
|
|
31
|
-
/** A MAC address, six pairs of hex digits with colons between them, for example `02:00:00:00:00:01`. */
|
|
32
|
-
export type MacAddress = `${string}:${string}:${string}:${string}:${string}:${string}`;
|
|
33
|
-
|
|
34
|
-
/** An address family. */
|
|
35
|
-
export type Family = "ipv4" | "ipv6";
|
|
36
|
-
|
|
37
|
-
/** Bits per second, for example `2G`, `500M` or `64k`. */
|
|
38
|
-
export type Rate = `${number}${"k" | "M" | "G"}`;
|
|
39
|
-
|
|
40
|
-
/** A log severity, most severe first. A threshold includes everything above it. */
|
|
41
|
-
export type Severity = "emergency" | "alert" | "critical" | "error" | "warning" | "notice" | "info" | "debug";
|
package/src/schema/device.ts
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import type { IP, Secret } from "./common";
|
|
2
|
-
import type { AclRule, Firewall } from "./firewall";
|
|
3
|
-
import type { Interface, Port, Vlan } from "./interfaces";
|
|
4
|
-
import type { PrefixSet, RoutePolicy } from "./policy";
|
|
5
|
-
import type { Routing, StaticRoute } from "./routing";
|
|
6
|
-
import type { Certificate, DhcpRelay, DhcpServer, FlowExport, Management, System, User } from "./system";
|
|
7
|
-
|
|
8
|
-
/** How the framework reaches the device. */
|
|
9
|
-
export type Connection<U extends string> = {
|
|
10
|
-
/** Management address. Absent for a device reached only through its console, `console`. */
|
|
11
|
-
host?: IP;
|
|
12
|
-
/** One of the device's `users`. Its password is the login. */
|
|
13
|
-
user: U;
|
|
14
|
-
/** SSH port. 22 when absent. */
|
|
15
|
-
port?: number;
|
|
16
|
-
/** The device's serial console, for `--console`: the way in before the device has a management address, or when its management network is down. */
|
|
17
|
-
console?: Console;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
/** A computer with SSH that holds the serial consoles of devices, such as a laptop beside the rack. It runs Python 3. */
|
|
21
|
-
export type Jump = {
|
|
22
|
-
/** Its address or name. */
|
|
23
|
-
host: string;
|
|
24
|
-
/** The user Circuit logs in as. It must be allowed to open the serial ports. */
|
|
25
|
-
user: string;
|
|
26
|
-
/** The user's password. */
|
|
27
|
-
password: Secret;
|
|
28
|
-
/** SSH port. 22 when absent. */
|
|
29
|
-
port?: number;
|
|
30
|
-
/** The jump host is reached through a Cloudflare Tunnel, so Circuit connects with `cloudflared access ssh`, which must be installed. */
|
|
31
|
-
cloudflared?: true;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/** A serial console, on a jump host or on the computer Circuit runs on. */
|
|
35
|
-
export type Console = {
|
|
36
|
-
/** The jump host the console cable is plugged into. When absent, the cable is plugged into the computer Circuit runs on. */
|
|
37
|
-
jump?: Jump;
|
|
38
|
-
/** The serial port: on Linux or macOS a path under `/dev`, where a path under `/dev/serial/by-path/` stays the same when two adapters swap names; on Windows a COM port, such as `COM3`. */
|
|
39
|
-
port: string;
|
|
40
|
-
/** Line speed in bits per second, such as 9600 or 115200. */
|
|
41
|
-
baud: number;
|
|
42
|
-
/** The console asks only for a password, with no name first. Circuit then types no name; `connection.user` still picks the password. */
|
|
43
|
-
passwordOnly?: true;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Virtual domains, on FortiOS: the device's own traffic kept apart from the traffic it routes. Everything is in `root` when absent.
|
|
48
|
-
*
|
|
49
|
-
* Multi-VDOM mode is turned on by hand, not by a plan: it moves the whole configuration into `root` and ends every session.
|
|
50
|
-
*/
|
|
51
|
-
export type Vdoms<I extends string> = {
|
|
52
|
-
/**
|
|
53
|
-
* A VDOM for the device's own traffic: FortiGuard, NTP, DNS and logging leave from it, by its own routes, so they never follow the routed traffic's default route. Everything not listed here stays in `root`.
|
|
54
|
-
*/
|
|
55
|
-
management: {
|
|
56
|
-
/** Its name, such as `mgmt`. Not `root`. */
|
|
57
|
-
name: string;
|
|
58
|
-
/** The ports and interfaces in it, by name. A LAG's member ports go with the LAG. */
|
|
59
|
-
interfaces: readonly I[];
|
|
60
|
-
/** Its static routes, such as its own default route. */
|
|
61
|
-
static?: readonly StaticRoute<I, never>[];
|
|
62
|
-
};
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
/** A separate routing table, with the interfaces that route in it. */
|
|
66
|
-
export type Vrf = {
|
|
67
|
-
/** What the VRF is for. */
|
|
68
|
-
description?: string;
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Everything one device runs. What is not written here is removed from the device or returned to its default.
|
|
73
|
-
*
|
|
74
|
-
* Type parameters are the names the device declares, so a reference to a name that does not exist fails to compile: N ports, V VLANs, I interfaces, P policies, S prefix sets, G BGP groups, A ACLs, AS address sets, U users, F VRFs, C certificates, T routing tables.
|
|
75
|
-
*/
|
|
76
|
-
export type Device<
|
|
77
|
-
Pl extends string = string,
|
|
78
|
-
M extends string = string,
|
|
79
|
-
N extends string = string,
|
|
80
|
-
V extends string = string,
|
|
81
|
-
I extends string = string,
|
|
82
|
-
P extends string = string,
|
|
83
|
-
S extends string = string,
|
|
84
|
-
G extends string = string,
|
|
85
|
-
A extends string = string,
|
|
86
|
-
AS extends string = string,
|
|
87
|
-
U extends string = string,
|
|
88
|
-
F extends string = string,
|
|
89
|
-
C extends string = string,
|
|
90
|
-
T extends string = string,
|
|
91
|
-
> = {
|
|
92
|
-
/** Hostname. */
|
|
93
|
-
name: string;
|
|
94
|
-
/** Operating system. It decides which adapter renders and applies the device. */
|
|
95
|
-
platform: Pl;
|
|
96
|
-
/** Hardware model. Decides which port names exist. */
|
|
97
|
-
model: M;
|
|
98
|
-
/** How the framework logs in. */
|
|
99
|
-
connection: Connection<NoInfer<U>>;
|
|
100
|
-
/** Device-wide settings. */
|
|
101
|
-
system?: System;
|
|
102
|
-
/** Logins, keyed by user name. Users not listed are removed. */
|
|
103
|
-
users?: Record<U, User>;
|
|
104
|
-
/** Ways in, and who may use them. */
|
|
105
|
-
management?: Management<NoInfer<I | N>, NoInfer<C>>;
|
|
106
|
-
/** Certificates, keyed by name. */
|
|
107
|
-
certificates?: Record<C, Certificate>;
|
|
108
|
-
/** VLANs, keyed by name. */
|
|
109
|
-
vlans?: Record<V, Vlan>;
|
|
110
|
-
/** Physical ports, keyed by `<speed>-<position>`. */
|
|
111
|
-
ports?: Partial<Record<N, Port<NoInfer<V>, NoInfer<A>, NoInfer<I>, NoInfer<F>>>>;
|
|
112
|
-
/** Interfaces that are not physical ports, keyed by name. */
|
|
113
|
-
interfaces?: Record<I, Interface<NoInfer<V>, NoInfer<F>>>;
|
|
114
|
-
/** Separate routing tables, keyed by name. */
|
|
115
|
-
vrfs?: Record<F, Vrf>;
|
|
116
|
-
/** Routing tables and rules, static routes, BGP, OSPF and route validation. */
|
|
117
|
-
routing?: Routing<NoInfer<P>, G, NoInfer<I | N>, NoInfer<F>, T>;
|
|
118
|
-
/** Route policies, keyed by name. */
|
|
119
|
-
policies?: Record<P, RoutePolicy<NoInfer<P>, NoInfer<S>>>;
|
|
120
|
-
/** Prefix sets that policies match on, keyed by name. */
|
|
121
|
-
prefix_sets?: Record<S, PrefixSet>;
|
|
122
|
-
/** Packet filtering and address translation. */
|
|
123
|
-
firewall?: Firewall<NoInfer<I | N>, AS>;
|
|
124
|
-
/** Hardware ACLs, keyed by name, applied to a port with `acl`. */
|
|
125
|
-
acls?: Record<A, readonly AclRule<NoInfer<V>>[]>;
|
|
126
|
-
/** DHCP servers, keyed by name. */
|
|
127
|
-
dhcp?: Record<string, DhcpServer<NoInfer<I | N>>>;
|
|
128
|
-
/** DHCP relays, keyed by name. */
|
|
129
|
-
dhcp_relay?: Record<string, DhcpRelay<NoInfer<I | N>>>;
|
|
130
|
-
/** Flow records or packet samples sent to collectors. */
|
|
131
|
-
flow_export?: FlowExport<NoInfer<I | N>>;
|
|
132
|
-
/** Advertise and learn neighbors with LLDP on every port, or only on the interfaces listed. A port may override it. */
|
|
133
|
-
lldp?: true | { interfaces: readonly NoInfer<I | N>[] };
|
|
134
|
-
/** Spanning tree on every switched port. A port may override it. */
|
|
135
|
-
stp?: {
|
|
136
|
-
/** Which variant runs. RSTP when absent. */
|
|
137
|
-
mode?: "stp" | "rstp" | "mstp";
|
|
138
|
-
/** Bridge priority, 0 to 61440 in steps of 4096. Lower wins the root election. */
|
|
139
|
-
priority?: number;
|
|
140
|
-
};
|
|
141
|
-
/** Forward in hardware where the platform can. An interface may override it. */
|
|
142
|
-
hardware_offload?: boolean;
|
|
143
|
-
/** Virtual domains, on FortiOS only: a management VDOM apart from the routed traffic. */
|
|
144
|
-
vdoms?: Vdoms<NoInfer<I | N>>;
|
|
145
|
-
};
|
package/src/schema/firewall.ts
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import type { Family, IP, Prefix, Rate } from "./common";
|
|
2
|
-
|
|
3
|
-
/** An IP protocol. `icmp` means ICMPv6 in an IPv6 rule. */
|
|
4
|
-
export type Protocol = "tcp" | "udp" | "icmp" | "gre" | "esp" | "ah" | "ospf" | "vrrp";
|
|
5
|
-
|
|
6
|
-
/** The state connection tracking assigns a packet. */
|
|
7
|
-
export type ConnectionState = "new" | "established" | "related" | "untracked" | "invalid";
|
|
8
|
-
|
|
9
|
-
/** Ports from `min` to `max`, both included. */
|
|
10
|
-
export type PortRange = { min: number; max: number };
|
|
11
|
-
|
|
12
|
-
/** A port, a range of ports, or any of several. */
|
|
13
|
-
export type Ports = number | PortRange | readonly (number | PortRange)[];
|
|
14
|
-
|
|
15
|
-
/** A TCP header flag. */
|
|
16
|
-
export type TcpFlag = "fin" | "syn" | "rst" | "psh" | "ack" | "urg";
|
|
17
|
-
|
|
18
|
-
/** Conditions on a packet. All must be true. A rule with addresses of one family applies to that family only. */
|
|
19
|
-
export type FilterMatch<I extends string, AS extends string> = {
|
|
20
|
-
/** Only packets of this family. */
|
|
21
|
-
family?: Family;
|
|
22
|
-
/** IP protocol. */
|
|
23
|
-
protocol?: Protocol;
|
|
24
|
-
/** Source address or prefix. */
|
|
25
|
-
src?: Prefix;
|
|
26
|
-
/** Destination address or prefix. */
|
|
27
|
-
dst?: Prefix;
|
|
28
|
-
/** Source is in this address set. */
|
|
29
|
-
src_set?: AS;
|
|
30
|
-
/** Destination is in this address set. */
|
|
31
|
-
dst_set?: AS;
|
|
32
|
-
/** Source port, or any of several. TCP and UDP only. */
|
|
33
|
-
src_port?: Ports;
|
|
34
|
-
/** Destination port, or any of several. TCP and UDP only. */
|
|
35
|
-
dst_port?: Ports;
|
|
36
|
-
/** Arrived on this interface. */
|
|
37
|
-
in_interface?: I;
|
|
38
|
-
/** Leaves through this interface. */
|
|
39
|
-
out_interface?: I;
|
|
40
|
-
/** Connection tracking state, any of these. */
|
|
41
|
-
state?: readonly ConnectionState[];
|
|
42
|
-
/** TCP flags that must be set, and flags that must not be. */
|
|
43
|
-
tcp_flags?: { set?: readonly TcpFlag[]; unset?: readonly TcpFlag[] };
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
/** One firewall rule. */
|
|
47
|
-
export type FilterRule<I extends string, AS extends string> = {
|
|
48
|
-
/** Shown beside the rule on the device. */
|
|
49
|
-
description?: string;
|
|
50
|
-
/** Which packets the rule applies to. Every packet when absent. */
|
|
51
|
-
match?: FilterMatch<I, AS>;
|
|
52
|
-
/** What happens to a matching packet. `reject` answers the sender, `drop` does not. */
|
|
53
|
-
action: "accept" | "drop" | "reject";
|
|
54
|
-
/** Send the rest of an accepted flow through the fast path, skipping the remaining rules. */
|
|
55
|
-
offload?: true;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
/** Rules evaluated in order, first match wins, then `default`. */
|
|
59
|
-
export type Chain<I extends string, AS extends string> = {
|
|
60
|
-
/** What happens to a packet no rule matched. Accept when absent. */
|
|
61
|
-
default?: "accept" | "drop";
|
|
62
|
-
/** Evaluated in order. */
|
|
63
|
-
rules?: readonly FilterRule<I, AS>[];
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
/** One address translation. */
|
|
67
|
-
export type NatRule<I extends string, AS extends string> = {
|
|
68
|
-
/** Shown beside the rule on the device. */
|
|
69
|
-
description?: string;
|
|
70
|
-
/** Which packets are translated. Every packet when absent. */
|
|
71
|
-
match?: FilterMatch<I, AS>;
|
|
72
|
-
} & (
|
|
73
|
-
| {
|
|
74
|
-
/** Use the address of the outgoing interface. */
|
|
75
|
-
action: "masquerade";
|
|
76
|
-
}
|
|
77
|
-
| {
|
|
78
|
-
/** `snat` rewrites the source, `dnat` the destination. */
|
|
79
|
-
action: "snat" | "dnat";
|
|
80
|
-
/** The address to rewrite to. */
|
|
81
|
-
to: IP;
|
|
82
|
-
/** The port to rewrite to. Unchanged when absent. */
|
|
83
|
-
to_port?: number;
|
|
84
|
-
}
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
/** Connection-tracking helpers that rewrite application payloads. None run unless listed. */
|
|
88
|
-
export type Helper = "ftp" | "tftp" | "sip" | "h323" | "pptp" | "rtsp" | "irc";
|
|
89
|
-
|
|
90
|
-
/** What the device filters and translates. */
|
|
91
|
-
export type Firewall<I extends string, AS extends string> = {
|
|
92
|
-
/** Named groups of addresses and prefixes, of either family, that rules match on. */
|
|
93
|
-
address_sets?: Record<AS, readonly (IP | Prefix)[]>;
|
|
94
|
-
/** Traffic to the device, through it, and from it. */
|
|
95
|
-
filter?: {
|
|
96
|
-
input?: Chain<I, NoInfer<AS>>;
|
|
97
|
-
forward?: Chain<I, NoInfer<AS>>;
|
|
98
|
-
output?: Chain<I, NoInfer<AS>>;
|
|
99
|
-
};
|
|
100
|
-
/** Source translation on the way out, destination translation on the way in. */
|
|
101
|
-
nat?: {
|
|
102
|
-
source?: readonly NatRule<I, NoInfer<AS>>[];
|
|
103
|
-
destination?: readonly NatRule<I, NoInfer<AS>>[];
|
|
104
|
-
};
|
|
105
|
-
/** Helpers that run. None when absent. */
|
|
106
|
-
helpers?: readonly Helper[];
|
|
107
|
-
/**
|
|
108
|
-
* Traffic to and from these prefixes passes without connection tracking. A flood toward them cannot fill the connection table, and rules see its packets in the state `untracked`. Everything is tracked when absent.
|
|
109
|
-
*
|
|
110
|
-
* Each address NAT uses inside one of these prefixes (a source translation's `to`, a destination translation's `to` or matched `dst`) stays tracked: Circuit writes two accept rules for it, one for traffic to it and one for traffic from it, before the untracked rules. Without them, a reply to that address would skip tracking and never be translated back.
|
|
111
|
-
*/
|
|
112
|
-
untracked?: readonly Prefix[];
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
/** A stateless rule evaluated in hardware where traffic arrives, before routing. */
|
|
116
|
-
export type AclRule<V extends string> = {
|
|
117
|
-
/** Shown beside the rule on the device. */
|
|
118
|
-
description?: string;
|
|
119
|
-
/** Which packets the rule applies to. Every packet when absent. */
|
|
120
|
-
match?: {
|
|
121
|
-
/** Only packets of this family. */
|
|
122
|
-
family?: Family;
|
|
123
|
-
/** IP protocol. */
|
|
124
|
-
protocol?: Protocol;
|
|
125
|
-
/** Source prefix. */
|
|
126
|
-
src?: Prefix;
|
|
127
|
-
/** Destination prefix. */
|
|
128
|
-
dst?: Prefix;
|
|
129
|
-
/** Source port, or any of several. */
|
|
130
|
-
src_port?: Ports;
|
|
131
|
-
/** Destination port, or any of several. */
|
|
132
|
-
dst_port?: Ports;
|
|
133
|
-
/** In this VLAN. */
|
|
134
|
-
vlan?: V;
|
|
135
|
-
};
|
|
136
|
-
/** What happens to a matching packet. */
|
|
137
|
-
action: "accept" | "drop";
|
|
138
|
-
/** Accepted traffic above this rate is dropped. On RouterOS it did not limit traffic the CPU routes; see its TRAPS.md. */
|
|
139
|
-
rate?: Rate;
|
|
140
|
-
};
|
package/src/schema/index.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export type * from "./common";
|
|
2
|
-
export type * from "./device";
|
|
3
|
-
export type * from "./firewall";
|
|
4
|
-
export type * from "./interfaces";
|
|
5
|
-
export type * from "./policy";
|
|
6
|
-
export type * from "./routing";
|
|
7
|
-
export type * from "./system";
|
|
8
|
-
export type * from "./time-zones";
|