@wenathlan/argan 2.0.84 → 2.0.93
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wenathlan/argan",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.93",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/wenathlan/devthink"
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"build": "vite build",
|
|
38
38
|
"start": "vite preview --host",
|
|
39
39
|
"preview": "vite preview --host",
|
|
40
|
-
"check": "tsc --noEmit"
|
|
40
|
+
"check": "tsc --noEmit",
|
|
41
|
+
"test": "vitest run"
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
44
|
"@hono/node-server": "^2.1.3",
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
// # dnssec.
|
|
2
|
-
// with the
|
|
3
|
-
//
|
|
1
|
+
// # dnssec.test — honest unit tests for the DNSSEC validation math, runnable
|
|
2
|
+
// with the vitest runner:
|
|
3
|
+
// pnpm test
|
|
4
4
|
import assert from "node:assert/strict";
|
|
5
|
-
import { describe, it } from "
|
|
5
|
+
import { describe, it } from "vitest";
|
|
6
6
|
import {
|
|
7
7
|
DNSSECALGORITHMS,
|
|
8
8
|
DNSSECDIGESTTYPES,
|
|
9
|
+
type DnsKey,
|
|
10
|
+
DnssecValidationError,
|
|
9
11
|
keyTag,
|
|
10
12
|
parseRrSig,
|
|
11
13
|
validateChainLink,
|
|
@@ -13,9 +15,7 @@ import {
|
|
|
13
15
|
validateSignatureLabels,
|
|
14
16
|
validateSignatureTtl,
|
|
15
17
|
validateSignatureWindow,
|
|
16
|
-
|
|
17
|
-
type DnsKey,
|
|
18
|
-
} from "../dnssec.validate.ts";
|
|
18
|
+
} from "../dnssec.ts";
|
|
19
19
|
|
|
20
20
|
/** A small DNSKEY whose key tag was computed by hand from the RFC 4034 Appendix B loop. */
|
|
21
21
|
const ZONEKEY: DnsKey = { flags: 256, protocol: 3, algorithm: 8, publicKey: "qrs=" };
|
|
@@ -23,7 +23,7 @@ const ZONEKEY: DnsKey = { flags: 256, protocol: 3, algorithm: 8, publicKey: "qrs
|
|
|
23
23
|
/** A fresh RRSIG presentation line over www.example.com. (2026 window). */
|
|
24
24
|
const SIGNATURELINE = "A 8 3 300 20261231235959 20260101000000 18928 www.example.com. dGVzdHNpZ25hdHVyZQ==";
|
|
25
25
|
|
|
26
|
-
describe("dnssec
|
|
26
|
+
describe("dnssec presentation parsing", () => {
|
|
27
27
|
it("parses an RRSIG line with its zone-file timestamps", () => {
|
|
28
28
|
const sig = parseRrSig(SIGNATURELINE);
|
|
29
29
|
assert.equal(sig.typeCovered, "A");
|
|
@@ -41,14 +41,11 @@ describe("dnssec.validate presentation parsing", () => {
|
|
|
41
41
|
assert.throws(() => parseRrSig("A 8 3"), DnssecValidationError);
|
|
42
42
|
assert.throws(() => parseRrSig("A 8 3 300 2026 20260101000000 1 example.com. aa"), DnssecValidationError);
|
|
43
43
|
// expiration before inception is structurally impossible
|
|
44
|
-
assert.throws(
|
|
45
|
-
() => parseRrSig("A 8 3 300 20260101000000 20261231235959 1 example.com. aa"),
|
|
46
|
-
DnssecValidationError,
|
|
47
|
-
);
|
|
44
|
+
assert.throws(() => parseRrSig("A 8 3 300 20260101000000 20261231235959 1 example.com. aa"), DnssecValidationError);
|
|
48
45
|
});
|
|
49
46
|
});
|
|
50
47
|
|
|
51
|
-
describe("dnssec
|
|
48
|
+
describe("dnssec key tag and chain math", () => {
|
|
52
49
|
it("computes the RFC 4034 Appendix B checksum by hand", () => {
|
|
53
50
|
// rdata = 01 00 03 08 aa bb → 256 + 0 + 768 + 8 + 43520 + 187 = 44739
|
|
54
51
|
assert.equal(keyTag(ZONEKEY), 44739);
|
|
@@ -75,15 +72,21 @@ describe("dnssec.validate key tag and chain math", () => {
|
|
|
75
72
|
assert.equal(unknownAlgorithm.ok ? "" : unknownAlgorithm.code, "unknown-algorithm");
|
|
76
73
|
// flags and protocol are part of the rdata, so each mutation recomputes its own DS tag
|
|
77
74
|
const strippedKey = { ...ZONEKEY, flags: 1 };
|
|
78
|
-
const noZoneKey = validateDsMatch(
|
|
75
|
+
const noZoneKey = validateDsMatch(
|
|
76
|
+
{ keyTag: keyTag(strippedKey), algorithm: 8, digestType: 2, digest: "aa" },
|
|
77
|
+
strippedKey,
|
|
78
|
+
);
|
|
79
79
|
assert.equal(noZoneKey.ok ? "" : noZoneKey.code, "not-a-zone-key");
|
|
80
80
|
const oldProtocolKey = { ...ZONEKEY, protocol: 2 };
|
|
81
|
-
const badProtocol = validateDsMatch(
|
|
81
|
+
const badProtocol = validateDsMatch(
|
|
82
|
+
{ keyTag: keyTag(oldProtocolKey), algorithm: 8, digestType: 2, digest: "aa" },
|
|
83
|
+
oldProtocolKey,
|
|
84
|
+
);
|
|
82
85
|
assert.equal(badProtocol.ok ? "" : badProtocol.code, "protocol-mismatch");
|
|
83
86
|
});
|
|
84
87
|
});
|
|
85
88
|
|
|
86
|
-
describe("dnssec
|
|
89
|
+
describe("dnssec clock and ttl windows", () => {
|
|
87
90
|
const sig = parseRrSig(SIGNATURELINE);
|
|
88
91
|
|
|
89
92
|
it("answers ok inside the validity window and names the reason outside", () => {
|
|
@@ -109,7 +112,11 @@ describe("dnssec.validate clock and ttl windows", () => {
|
|
|
109
112
|
assert.deepEqual(validateSignatureTtl(sig, 300, 300), { ok: true });
|
|
110
113
|
const mismatch = validateSignatureTtl(sig, 600, 300);
|
|
111
114
|
assert.equal(mismatch.ok ? "" : mismatch.code, "ttl-mismatch");
|
|
112
|
-
const ceiling = validateSignatureTtl(
|
|
115
|
+
const ceiling = validateSignatureTtl(
|
|
116
|
+
parseRrSig("A 8 3 60 20261231235959 20260101000000 1 example.com. aa"),
|
|
117
|
+
300,
|
|
118
|
+
300,
|
|
119
|
+
);
|
|
113
120
|
assert.equal(ceiling.ok ? "" : ceiling.code, "ttl-exceeds-original");
|
|
114
121
|
});
|
|
115
122
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// #
|
|
2
|
-
//
|
|
3
|
-
//
|
|
1
|
+
// # zonediff.test — honest unit tests for the zone diff, runnable with the
|
|
2
|
+
// vitest runner:
|
|
3
|
+
// pnpm test
|
|
4
4
|
import assert from "node:assert/strict";
|
|
5
|
-
import { describe, it } from "
|
|
5
|
+
import { describe, it } from "vitest";
|
|
6
6
|
import { nextSerial } from "../argan.ts";
|
|
7
7
|
import {
|
|
8
8
|
diffZoneFiles,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
serialForPublication,
|
|
13
13
|
ZoneDiffError,
|
|
14
14
|
type ZoneRecord,
|
|
15
|
-
} from "../
|
|
15
|
+
} from "../zonediff.ts";
|
|
16
16
|
|
|
17
17
|
const ORIGIN = "example.com.";
|
|
18
18
|
|
|
@@ -21,7 +21,7 @@ function record(name: string, type: string, ttl: number | undefined, data: strin
|
|
|
21
21
|
return { name, type, ttl, data };
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
describe("
|
|
24
|
+
describe("zonediff parser", () => {
|
|
25
25
|
it("parses absolute and relative owners, @, ttl and class in both orders", () => {
|
|
26
26
|
const text = [
|
|
27
27
|
"example.com. 300 IN SOA ns1.example.com. hostmaster.example.com. 1 2 3 4 5",
|
|
@@ -92,7 +92,7 @@ describe("zone.diff parser", () => {
|
|
|
92
92
|
});
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
describe("
|
|
95
|
+
describe("zonediff planner", () => {
|
|
96
96
|
it("answers an empty diff for identical records", () => {
|
|
97
97
|
const zone = [
|
|
98
98
|
record("example.com.", "A", 300, "192.0.2.1"),
|
|
@@ -126,8 +126,14 @@ describe("zone.diff planner", () => {
|
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
it("never changes on round robin order and reports ttl-only updates", () => {
|
|
129
|
-
const current = [
|
|
130
|
-
|
|
129
|
+
const current = [
|
|
130
|
+
record("api.example.com.", "A", 300, "192.0.2.1"),
|
|
131
|
+
record("api.example.com.", "A", 300, "192.0.2.2"),
|
|
132
|
+
];
|
|
133
|
+
const reordered = [
|
|
134
|
+
record("api.example.com.", "A", 300, "192.0.2.2"),
|
|
135
|
+
record("api.example.com.", "A", 300, "192.0.2.1"),
|
|
136
|
+
];
|
|
131
137
|
assert.deepEqual(diffZones(current, reordered), { creates: [], deletes: [], updates: [] });
|
|
132
138
|
const rettl = current.map((entry) => record(entry.name, entry.type, 600, entry.data));
|
|
133
139
|
const diff = diffZones(current, rettl);
|