From 8b1ca98dd2e24ae25ee15318323d651cb88fffd9 Mon Sep 17 00:00:00 2001 From: Kjartan Hrafnkelsson Date: Thu, 2 May 2024 23:02:40 +0000 Subject: [PATCH] initial git push --- .gitignore | 2 + .vscode/settings.json | 3 ++ gen.ts | 110 ++++++++++++++++++++++++++++++++++++++++++ readme.md | 31 ++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 gen.ts create mode 100644 readme.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a777273 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +gen +aspa-*.json \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b943dbc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "deno.enable": true +} \ No newline at end of file diff --git a/gen.ts b/gen.ts new file mode 100644 index 0000000..cd4a20d --- /dev/null +++ b/gen.ts @@ -0,0 +1,110 @@ +import { parseArgs } from "https://deno.land/std@0.207.0/cli/parse_args.ts"; + +type ASN = `AS${string}`; + +interface ASA { + customer: ASN; + providers: ASN[]; + ta: string; +} + +const printf = console.log; + +const flags = parseArgs(Deno.args, { + string: ["input", "output"], + boolean: ["strict", "verbose", "help"], + alias: { + i: "input", + o: "output", + s: "strict", + v: "verbose", + h: "help" + } +}); + +if (flags.help) { + printf(`Usage: ${Deno.execPath()} [OPTIONS] +Options: + --help, -h Show this menu. + --verbose, -v Show warnings. + --input, -i The input file generated by \`routinator\`. (required) + --output, -i The file to output the BIRD2 function to. + --strict, -s Consider paths without ASPA invalid (NOT RECOMMENDED).`); + + Deno.exit(0); +} + +let failed = false; +if (!flags.input) { + failed = true; + printf("(error) `--input` flag not specified."); +} + +if (!flags.output && flags.verbose) { + printf("(warn) `--output` flag not specified."); +} + +if (failed) { + Deno.exit(1); +} + +const data = await Deno.readTextFile(flags.input as string); // we know flags.input will not be undefined by this point. + +const json = parseData(data); +if (!json) { + printf(`(error) could not parse json from \`${flags.input}\``); + Deno.exit(2); +} + +const aspas: ASA[] = json.aspas; +if (!aspas) { + printf(`(error) property \`aspas\` does not exist on the parsed JSON from \`${flags.input}\``); + Deno.exit(3); +} + +let txt = "function is_aspa_valid () {\n"; + +const LEADING_AS = /^AS/g; +for (const {customer, providers} of aspas) { + const asn = customer.replace(LEADING_AS, ''); + + txt += ` # does the AS path include ${customer}?\n` + txt += ` if (bgp_path ~ [= * ${asn} * =]) then {\n`; + txt += ` # does the AS path include [carrier's asn, ${customer}]?\n` + for (const provider of providers) { + const carrier = provider.replace(LEADING_AS, ''); + + txt += ` if (bgp_path ~ [= * ${carrier} ${asn} * =]) then return true;\n`; + } + txt += ' return false;\n'; + txt += ' }\n\n' +} + +if (flags.strict) { + txt += ' # (strict mode) if no previous condition matches there exists no ASPA for the path; it is invalid.\n'; + txt += ' return false;\n'; +} else { + txt += ' # to avoid breaking stuff, assume the path is valid if no ASA exists.\n'; + txt += ' return true;\n'; +} +txt += '}\n'; + +if (!flags.output) { + console.log(txt); + + Deno.exit(0); +} + +try { + await Deno.writeTextFile(flags.output, txt); +} catch (e) { + printf(`(error) writing to disk raised: ${e}`); +} + +function parseData(data: string) { + try { + return JSON.parse(data); + } catch { + return null; + } +} \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..0a18ac6 --- /dev/null +++ b/readme.md @@ -0,0 +1,31 @@ +## "Compilation" to a stand-alone binary + +This is as easy as running the following command: + +``` +deno compile --allow-read --allow-write ./gen.ts +``` + +# my sticky notes: + +## 1: + +the as_path filters used: + +is the asn in the path? +`bgp_path ~ [= * * =]` + +is the carrier + the asn in the path? +`bgp_path ~ [= * * =]` + +## 2: + +get just the aspa dump from routinator: + +``` +routinator --enable-aspa vrps -f json -o /root/dump.json --no-route-origins --no-router-keys +``` + +this is probably missing a flag to skip tls verification for idiots (the ASAs are signed anyway?): + +`[WARN] RRDP https://rpki.cnnic.cn/rrdp/notify.xml: error sending request for url (https://rpki.cnnic.cn/rrdp/notify.xml): error trying to connect: invalid peer certificate: UnknownIssuer` \ No newline at end of file