pmcf 1.76.3 → 1.77.1

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": "pmcf",
3
- "version": "1.76.3",
3
+ "version": "1.77.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -0,0 +1,22 @@
1
+ export function dnsFullName(name) {
2
+ return name.endsWith(".") ? name : name + ".";
3
+ }
4
+
5
+ export function DNSRecord(key, type, ...values) {
6
+ values = values.map(v => (typeof v === "number" ? String(v).padStart(3) : v));
7
+
8
+ return {
9
+ key,
10
+ toString: (maxKeyLength, ttl) =>
11
+ `${key.padEnd(maxKeyLength, " ")} ${ttl} IN ${type.padEnd(
12
+ 5,
13
+ " "
14
+ )} ${values.join(" ")}`
15
+ };
16
+ }
17
+
18
+ export function dnsFormatParameters(parameters) {
19
+ return Object.entries(parameters)
20
+ .map(([name, value]) => (value !== undefined ? `${name}="${value}"` : name))
21
+ .join(" ");
22
+ }
package/src/dns.mjs CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  normalizeIPAddress,
8
8
  isLinkLocal
9
9
  } from "./utils.mjs";
10
+ import { DNSRecord, dnsFullName, dnsFormatParameters } from "./dns-utils.mjs";
10
11
  import { Base } from "./base.mjs";
11
12
  import { addType } from "./types.mjs";
12
13
  import { serviceAddresses } from "./service.mjs";
@@ -175,10 +176,6 @@ export class DNSService extends Base {
175
176
  }
176
177
  }
177
178
 
178
- function fullName(name) {
179
- return name.endsWith(".") ? name : name + ".";
180
- }
181
-
182
179
  async function generateZoneDefs(dns, targetDir) {
183
180
  const ttl = dns.recordTTL;
184
181
  const updates = [Math.ceil(Date.now() / 1000), ...dns.soaUpdates].join(" ");
@@ -192,24 +189,9 @@ async function generateZoneDefs(dns, targetDir) {
192
189
 
193
190
  let maxKeyLength;
194
191
 
195
- const createRecord = (key, type, ...values) => {
196
- values = values.map(v =>
197
- typeof v === "number" ? String(v).padStart(3) : v
198
- );
199
-
200
- return {
201
- key,
202
- toString: () =>
203
- `${key.padEnd(maxKeyLength, " ")} ${ttl} IN ${type.padEnd(
204
- 5,
205
- " "
206
- )} ${values.join(" ")}`
207
- };
208
- };
209
-
210
192
  for (const mail of dns.owner.findServices({ type: "smtp" })) {
211
193
  records.add(
212
- createRecord("@", "MX", mail.priority, fullName(mail.domainName))
194
+ DNSRecord("@", "MX", mail.priority, dnsFullName(mail.domainName))
213
195
  );
214
196
  }
215
197
 
@@ -217,21 +199,27 @@ async function generateZoneDefs(dns, targetDir) {
217
199
  //console.log(dns.owner.fullName, domain, nameService.domainName, rname);
218
200
  const reverseZones = new Map();
219
201
 
220
- const SOARecord = createRecord(
202
+ const SOARecord = DNSRecord(
221
203
  "@",
222
204
  "SOA",
223
- fullName(nameService.domainName),
224
- fullName(rname),
205
+ dnsFullName(nameService.domainName),
206
+ dnsFullName(rname),
225
207
  `(${updates})`
226
208
  );
227
209
 
228
- const NSRecord = createRecord(
210
+ const NSRecord = DNSRecord(
229
211
  "@",
230
212
  "NS",
231
- fullName(nameService.ipAddressOrDomainName)
213
+ dnsFullName(nameService.ipAddressOrDomainName)
232
214
  );
233
215
 
234
- const ALPNRecord = createRecord("@", "HTTPS", 1, ".", "alpn=h3");
216
+ const ALPNRecord = DNSRecord(
217
+ "@",
218
+ "HTTPS",
219
+ 1,
220
+ ".",
221
+ dnsFormatParameters({ alpn: "h3" })
222
+ );
235
223
 
236
224
  const zone = {
237
225
  id: domain,
@@ -248,7 +236,7 @@ async function generateZoneDefs(dns, targetDir) {
248
236
  records: new Set([
249
237
  SOARecord,
250
238
  NSRecord,
251
- createRecord(fullName(`version.catalog.${domain}`), "TXT", '"1"')
239
+ DNSRecord(dnsFullName(`version.catalog.${domain}`), "TXT", '"1"')
252
240
  ])
253
241
  };
254
242
 
@@ -280,8 +268,8 @@ async function generateZoneDefs(dns, targetDir) {
280
268
  addresses.add(address);
281
269
 
282
270
  zone.records.add(
283
- createRecord(
284
- fullName(domainName),
271
+ DNSRecord(
272
+ dnsFullName(domainName),
285
273
  isIPv6Address(address) ? "AAAA" : "A",
286
274
  normalizeIPAddress(address)
287
275
  )
@@ -303,10 +291,10 @@ async function generateZoneDefs(dns, targetDir) {
303
291
 
304
292
  for (const domainName of host.domainNames) {
305
293
  reverseZone.records.add(
306
- createRecord(
307
- fullName(reverseArpaAddress(address)),
294
+ DNSRecord(
295
+ dnsFullName(reverseArpaAddress(address)),
308
296
  "PTR",
309
- fullName(domainName)
297
+ dnsFullName(domainName)
310
298
  )
311
299
  );
312
300
  }
@@ -316,23 +304,11 @@ async function generateZoneDefs(dns, targetDir) {
316
304
  if (!hosts.has(host)) {
317
305
  hosts.add(host);
318
306
  for (const service of host.findServices()) {
319
- if (service.master && service.alias) {
320
- zone.records.add(
321
- createRecord(service.alias, "CNAME", fullName(domainName))
322
- );
323
- }
324
-
325
- if (dns.hasSVRRecords && service.srvPrefix) {
326
- zone.records.add(
327
- createRecord(
328
- fullName(`${service.srvPrefix}.${domainName}`),
329
- "SRV",
330
- service.priority,
331
- service.weight,
332
- service.port,
333
- fullName(host.domainName)
334
- )
335
- );
307
+ for (const record of service.dnsRecordsForDomainName(
308
+ domainName,
309
+ dns.hasSVRRecords
310
+ )) {
311
+ zone.records.add(record);
336
312
  }
337
313
  }
338
314
  }
@@ -345,10 +321,10 @@ async function generateZoneDefs(dns, targetDir) {
345
321
  if (zone.type !== "catalog") {
346
322
  const hash = createHmac("md5", zone.id).digest("hex");
347
323
  catalogZone.records.add(
348
- createRecord(
324
+ DNSRecord(
349
325
  `${hash}.zones.catalog.${domain}.`,
350
326
  "PTR",
351
- fullName(zone.id)
327
+ dnsFullName(zone.id)
352
328
  )
353
329
  );
354
330
  }
@@ -376,7 +352,7 @@ async function generateZoneDefs(dns, targetDir) {
376
352
  await writeLines(
377
353
  join(targetDir, "var/lib/named"),
378
354
  zone.file,
379
- zone.records
355
+ [...zone.records].map(r => r.toString(maxKeyLength, ttl))
380
356
  );
381
357
  }
382
358
 
package/src/service.mjs CHANGED
@@ -2,13 +2,28 @@ import { Base } from "./base.mjs";
2
2
  import { addType } from "./types.mjs";
3
3
  import { asArray } from "./utils.mjs";
4
4
  import { networkAddressProperties } from "./network-support.mjs";
5
+ import { DNSRecord, dnsFullName, dnsFormatParameters } from "./dns-utils.mjs";
5
6
 
6
7
  const ServiceTypes = {
7
8
  dns: { protocol: "udp", port: 53, tls: false },
8
9
  ldap: { protocol: "tcp", port: 389, tls: false },
9
10
  ldaps: { protocol: "tcp", port: 636, tls: true },
10
11
  http: { protocol: "tcp", port: 80, tls: false },
11
- https: { protocol: "tcp", port: 443, tls: true },
12
+ https: {
13
+ protocol: "tcp",
14
+ port: 443,
15
+ tls: true,
16
+ dnsRecord: { type: "HTTPS", parameters: { alpn: "h2" } }
17
+ },
18
+ http3: {
19
+ protocol: "tcp",
20
+ port: 443,
21
+ tls: true,
22
+ dnsRecord: {
23
+ type: "HTTPS",
24
+ parameters: { "no-default-alpn": undefined, alpn: "h3" }
25
+ }
26
+ },
12
27
  rtsp: { protocol: "tcp", port: 554, tls: false },
13
28
  smtp: { protocol: "tcp", port: 25, tls: false },
14
29
  ssh: { protocol: "tcp", port: 22, tls: false },
@@ -176,8 +191,56 @@ export class Service extends Base {
176
191
  return `_${this.type}._${st.protocol}`;
177
192
  }
178
193
  }
194
+
195
+ dnsRecordsForDomainName(domainName, hasSVRRecords) {
196
+ const records = [];
197
+ if (this.master && this.alias) {
198
+ records.push(DNSRecord(this.alias, "CNAME", dnsFullName(domainName)));
199
+ }
200
+
201
+ if (hasSVRRecords && this.srvPrefix) {
202
+ records.push(
203
+ DNSRecord(
204
+ dnsFullName(`${this.srvPrefix}.${domainName}`),
205
+ "SRV",
206
+ this.priority,
207
+ this.weight,
208
+ this.port,
209
+ dnsFullName(this.domainName)
210
+ )
211
+ );
212
+ }
213
+
214
+ const dnsRecord = ServiceTypes[this.type]?.dnsRecord;
215
+ if (dnsRecord) {
216
+ records.push(
217
+ DNSRecord(
218
+ dnsFullName(domainName),
219
+ dnsRecord.type,
220
+ this.priority,
221
+ ".",
222
+ dnsFormatParameters(dnsRecord.parameters)
223
+ )
224
+ );
225
+
226
+ if (this.master && this.alias) {
227
+ records.push(
228
+ DNSRecord(
229
+ this.alias,
230
+ dnsRecord.type,
231
+ this.priority,
232
+ dnsFullName(domainName),
233
+ dnsFormatParameters(dnsRecord.parameters)
234
+ )
235
+ );
236
+ }
237
+ }
238
+
239
+ return records;
240
+ }
179
241
  }
180
242
 
243
+
181
244
  export const sortByPriority = (a, b) => a.priority - b.priority;
182
245
 
183
246
  export function serviceAddresses(
@@ -0,0 +1,6 @@
1
+ export function dnsFullName(name: any): any;
2
+ export function DNSRecord(key: any, type: any, ...values: any[]): {
3
+ key: any;
4
+ toString: (maxKeyLength: any, ttl: any) => string;
5
+ };
6
+ export function dnsFormatParameters(parameters: any): string;
@@ -134,6 +134,10 @@ export class Service extends Base {
134
134
  get protocol(): any;
135
135
  get tls(): any;
136
136
  get srvPrefix(): string;
137
+ dnsRecordsForDomainName(domainName: any, hasSVRRecords: any): {
138
+ key: any;
139
+ toString: (maxKeyLength: any, ttl: any) => string;
140
+ }[];
137
141
  #private;
138
142
  }
139
143
  export function sortByPriority(a: any, b: any): number;