pmcf 4.19.2 → 4.20.0
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 +93 -72
- package/package.json +19 -19
- package/src/base.mjs +23 -241
- package/src/cli.mjs +4 -4
- package/src/cluster.mjs +13 -11
- package/src/extra-source-service.mjs +7 -10
- package/src/host.mjs +30 -44
- package/src/initialization-context.mjs +324 -0
- package/src/location.mjs +4 -14
- package/src/module.mjs +1 -0
- package/src/network-interfaces/ethernet.mjs +3 -5
- package/src/network-interfaces/loopback.mjs +2 -4
- package/src/network-interfaces/network-interface.mjs +3 -5
- package/src/network-interfaces/skeleton.mjs +9 -3
- package/src/network-interfaces/tun.mjs +2 -4
- package/src/network-interfaces/wireguard.mjs +3 -5
- package/src/network-interfaces/wlan.mjs +4 -7
- package/src/network.mjs +10 -8
- package/src/owner.mjs +7 -31
- package/src/root.mjs +4 -73
- package/src/service-owner.mjs +19 -18
- package/src/service.mjs +13 -18
- package/src/services/alpm.mjs +4 -9
- package/src/services/bind.mjs +424 -388
- package/src/services/chrony.mjs +3 -5
- package/src/services/headscale.mjs +2 -4
- package/src/services/influxdb.mjs +2 -4
- package/src/services/kea.mjs +6 -10
- package/src/services/mosquitto.mjs +2 -4
- package/src/services/openldap.mjs +2 -4
- package/src/services/postfix.mjs +2 -4
- package/src/services/systemd-journal-remote.mjs +2 -4
- package/src/services/systemd-journal-upload.mjs +9 -10
- package/src/services/systemd-journald.mjs +2 -4
- package/src/services/systemd-resolved.mjs +42 -42
- package/src/services/systemd-timesyncd.mjs +9 -13
- package/src/services/tailscale.mjs +5 -2
- package/src/subnet.mjs +9 -5
- package/types/base.d.mts +0 -180
- package/types/cli.d.mts +0 -10
- package/types/cluster.d.mts +0 -507
- package/types/dns-utils.d.mts +0 -14
- package/types/endpoint.d.mts +0 -79
- package/types/extra-source-service.d.mts +0 -1033
- package/types/hooks.d.mts +0 -2
- package/types/host-utils.d.mts +0 -1
- package/types/host.d.mts +0 -285
- package/types/location.d.mts +0 -379
- package/types/module.d.mts +0 -36
- package/types/network-address.d.mts +0 -41
- package/types/network-interfaces/ethernet.d.mts +0 -1189
- package/types/network-interfaces/loopback.d.mts +0 -1140
- package/types/network-interfaces/network-interface.d.mts +0 -1158
- package/types/network-interfaces/skeleton.d.mts +0 -30
- package/types/network-interfaces/tun.d.mts +0 -1131
- package/types/network-interfaces/wireguard.d.mts +0 -1131
- package/types/network-interfaces/wlan.d.mts +0 -1734
- package/types/network-support.d.mts +0 -193
- package/types/network.d.mts +0 -702
- package/types/owner.d.mts +0 -235
- package/types/root.d.mts +0 -10
- package/types/service-owner.d.mts +0 -14
- package/types/service-types.d.mts +0 -246
- package/types/service.d.mts +0 -689
- package/types/services/alpm.d.mts +0 -805
- package/types/services/bind.d.mts +0 -1574
- package/types/services/chrony.d.mts +0 -1310
- package/types/services/headscale.d.mts +0 -801
- package/types/services/influxdb.d.mts +0 -812
- package/types/services/kea.d.mts +0 -945
- package/types/services/mosquitto.d.mts +0 -876
- package/types/services/openldap.d.mts +0 -793
- package/types/services/postfix.d.mts +0 -784
- package/types/services/systemd-journal-remote.d.mts +0 -1030
- package/types/services/systemd-journal-upload.d.mts +0 -932
- package/types/services/systemd-journald.d.mts +0 -1317
- package/types/services/systemd-resolved.d.mts +0 -1644
- package/types/services/systemd-timesyncd.d.mts +0 -1459
- package/types/services/tailscale.d.mts +0 -781
- package/types/subnet.d.mts +0 -57
- package/types/utils.d.mts +0 -37
package/src/services/bind.mjs
CHANGED
|
@@ -5,15 +5,15 @@ import { isLinkLocal, reverseArpa } from "ip-utilties";
|
|
|
5
5
|
import {
|
|
6
6
|
addType,
|
|
7
7
|
default_attribute_writable,
|
|
8
|
-
|
|
9
|
-
string_collection_attribute_writable,
|
|
8
|
+
duration_attribute_writable,
|
|
10
9
|
string_set_attribute_writable,
|
|
11
10
|
boolean_attribute_writable_true,
|
|
12
11
|
boolean_attribute_writable_false,
|
|
13
|
-
|
|
12
|
+
integer_attribute_writable,
|
|
14
13
|
name_attribute_writable
|
|
15
14
|
} from "pacc";
|
|
16
15
|
import {
|
|
16
|
+
Base,
|
|
17
17
|
ExtraSourceService,
|
|
18
18
|
serviceEndpoints,
|
|
19
19
|
addresses,
|
|
@@ -31,346 +31,142 @@ import { ServiceTypeDefinition } from "../service.mjs";
|
|
|
31
31
|
import { ExtraSourceServiceTypeDefinition } from "../extra-source-service.mjs";
|
|
32
32
|
import { addHook } from "../hooks.mjs";
|
|
33
33
|
|
|
34
|
-
const
|
|
35
|
-
name: "bind-view",
|
|
36
|
-
key: "name",
|
|
37
|
-
attributes: {
|
|
38
|
-
name: { ...name_attribute_writable },
|
|
39
|
-
access: {
|
|
40
|
-
type: networkAddressType,
|
|
41
|
-
collection: true,
|
|
42
|
-
writable: true
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
};
|
|
34
|
+
const bindNetworkAddressTypes = networkAddressType + "|bind_group";
|
|
46
35
|
|
|
47
|
-
const
|
|
48
|
-
name: "
|
|
49
|
-
|
|
50
|
-
specializationOf: ServiceTypeDefinition,
|
|
51
|
-
owners: ServiceTypeDefinition.owners,
|
|
36
|
+
const BindGroupTypeDefinition = {
|
|
37
|
+
name: "bind_group",
|
|
38
|
+
priority: 1,
|
|
52
39
|
key: "name",
|
|
53
40
|
attributes: {
|
|
54
|
-
|
|
55
|
-
|
|
41
|
+
name: name_attribute_writable,
|
|
42
|
+
access: {
|
|
43
|
+
type: bindNetworkAddressTypes,
|
|
56
44
|
collection: true,
|
|
57
45
|
writable: true
|
|
58
|
-
}
|
|
59
|
-
|
|
46
|
+
},
|
|
47
|
+
excludeInterfaceKinds: string_set_attribute_writable,
|
|
48
|
+
exclude: {
|
|
49
|
+
...default_attribute_writable,
|
|
50
|
+
type: networkAddressType,
|
|
51
|
+
collection: true
|
|
52
|
+
},
|
|
53
|
+
entries: {
|
|
60
54
|
type: networkAddressType + "|location|owner",
|
|
61
55
|
collection: true,
|
|
62
56
|
writable: true
|
|
63
57
|
},
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
sharedWith: { ...default_attribute_writable, type: "bind_group" },
|
|
59
|
+
allowedUpdates: {
|
|
60
|
+
type: bindNetworkAddressTypes,
|
|
66
61
|
collection: true,
|
|
67
62
|
writable: true
|
|
68
63
|
},
|
|
69
|
-
|
|
70
|
-
...default_attribute_writable,
|
|
71
|
-
type: networkAddressType,
|
|
72
|
-
collection: true
|
|
73
|
-
},
|
|
74
|
-
internal: {
|
|
75
|
-
...default_attribute_writable,
|
|
76
|
-
type: networkAddressType,
|
|
77
|
-
collection: true
|
|
78
|
-
},
|
|
79
|
-
hasSVRRecords: boolean_attribute_writable_false,
|
|
64
|
+
notify: boolean_attribute_writable_false,
|
|
80
65
|
hasCatalog: boolean_attribute_writable_true,
|
|
66
|
+
hasReverse: boolean_attribute_writable_false,
|
|
67
|
+
hasSVRRecords: boolean_attribute_writable_false,
|
|
81
68
|
hasLinkLocalAdresses: boolean_attribute_writable_false,
|
|
82
69
|
hasLocationRecord: boolean_attribute_writable_true,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
70
|
+
|
|
71
|
+
recordTTL: { ...duration_attribute_writable, default: "1W" },
|
|
72
|
+
serial: {
|
|
73
|
+
...integer_attribute_writable,
|
|
74
|
+
default: Math.ceil(Date.now() / 1000)
|
|
88
75
|
},
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
retry: { ...string_attribute_writable, default: 72000 },
|
|
94
|
-
expire: { ...string_attribute_writable, default: 600000 },
|
|
95
|
-
minimum: { ...string_attribute_writable, default: 60000 },
|
|
96
|
-
allowedUpdates: string_collection_attribute_writable,
|
|
97
|
-
primaries: {
|
|
98
|
-
...default_attribute_writable,
|
|
99
|
-
type: networkAddressType,
|
|
100
|
-
collection: true
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
service: {
|
|
104
|
-
systemdService: "bind.service",
|
|
105
|
-
extends: ["dns"],
|
|
106
|
-
services: {
|
|
107
|
-
"bind-statistics": {
|
|
108
|
-
endpoints: [
|
|
109
|
-
{
|
|
110
|
-
family: "IPv4",
|
|
111
|
-
port: 19521,
|
|
112
|
-
protocol: "tcp",
|
|
113
|
-
pathname: "/",
|
|
114
|
-
tls: false,
|
|
115
|
-
kind: "loopback"
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
family: "IPv6",
|
|
119
|
-
port: 19521,
|
|
120
|
-
protocol: "tcp",
|
|
121
|
-
pathname: "/",
|
|
122
|
-
tls: false,
|
|
123
|
-
kind: "loopback"
|
|
124
|
-
}
|
|
125
|
-
]
|
|
126
|
-
},
|
|
127
|
-
"bind-rdnc": {
|
|
128
|
-
endpoints: [
|
|
129
|
-
{
|
|
130
|
-
family: "IPv4",
|
|
131
|
-
port: 953,
|
|
132
|
-
protocol: "tcp",
|
|
133
|
-
tls: false,
|
|
134
|
-
kind: "loopback"
|
|
135
|
-
}
|
|
136
|
-
]
|
|
137
|
-
}
|
|
138
|
-
}
|
|
76
|
+
refresh: { ...duration_attribute_writable, default: 36000 },
|
|
77
|
+
retry: { ...duration_attribute_writable, default: 72000 },
|
|
78
|
+
expire: { ...duration_attribute_writable, default: 600000 },
|
|
79
|
+
minimum: { ...duration_attribute_writable, default: 60000 }
|
|
139
80
|
}
|
|
140
81
|
};
|
|
141
82
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return [`${prefix} {`, body, "};"];
|
|
83
|
+
class BindGroup extends Base {
|
|
84
|
+
static typeDefinition = BindGroupTypeDefinition;
|
|
85
|
+
static {
|
|
86
|
+
addType(this);
|
|
147
87
|
}
|
|
148
88
|
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export class BindService extends ExtraSourceService {
|
|
89
|
+
access = [];
|
|
153
90
|
allowedUpdates = [];
|
|
154
|
-
|
|
155
|
-
|
|
91
|
+
entries = [];
|
|
92
|
+
exclude = new Set();
|
|
93
|
+
excludeInterfaceKinds = new Set();
|
|
94
|
+
notify = true;
|
|
156
95
|
hasCatalog = true;
|
|
96
|
+
hasSVRRecords = true;
|
|
157
97
|
hasLinkLocalAdresses =
|
|
158
|
-
|
|
159
|
-
hasLocationRecord = true;
|
|
160
|
-
notify = true;
|
|
161
|
-
_zones = [];
|
|
162
|
-
_trusted = [];
|
|
163
|
-
_exclude = new Set([]);
|
|
164
|
-
|
|
165
|
-
excludeInterfaceKinds = new Set();
|
|
166
|
-
|
|
167
|
-
serial = Math.ceil(Date.now() / 1000);
|
|
168
|
-
refresh = 36000;
|
|
169
|
-
retry = 72000;
|
|
170
|
-
expire = 600000;
|
|
171
|
-
minimum = 60000;
|
|
172
|
-
static {
|
|
173
|
-
addType(this);
|
|
174
|
-
addServiceType(this.typeDefinition.service, this.typeDefinition.name);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
static get typeDefinition() {
|
|
178
|
-
return BindServiceTypeDefinition;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
constructor(owner, data) {
|
|
182
|
-
super(owner, data);
|
|
183
|
-
|
|
184
|
-
this.views = {};
|
|
185
|
-
|
|
186
|
-
for (const name of ["internal", "protected"]) {
|
|
187
|
-
this.views[name] = {
|
|
188
|
-
name,
|
|
189
|
-
access: []
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
this.views.protected.inView = this.views.internal;
|
|
194
|
-
this.views.protected.access = ["!internal"];
|
|
195
|
-
}
|
|
98
|
+
BindGroupTypeDefinition.attributes.hasLinkLocalAdresses.default;
|
|
196
99
|
|
|
197
|
-
|
|
198
|
-
return BindServiceTypeDefinition.name;
|
|
199
|
-
}
|
|
100
|
+
recordTTL = "1W";
|
|
200
101
|
|
|
201
|
-
get
|
|
202
|
-
|
|
203
|
-
return this.primaries ? "secondary" : "primary";
|
|
102
|
+
get service() {
|
|
103
|
+
return this.owner;
|
|
204
104
|
}
|
|
205
105
|
|
|
206
106
|
get soaUpdates() {
|
|
207
107
|
return [this.serial, this.refresh, this.retry, this.expire, this.minimum];
|
|
208
108
|
}
|
|
209
109
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
set internal(value) {
|
|
227
|
-
this.views.internal.access.push(value);
|
|
228
|
-
}
|
|
110
|
+
get defaultRecords() {
|
|
111
|
+
/*
|
|
112
|
+
const ss = this.location.services.filter(s=>s.types.has('dns') && s.priority>=300);
|
|
113
|
+
const ss = [
|
|
114
|
+
...this.location.expression("services[types['dns'] && priority>=300]")
|
|
115
|
+
].sort(sortAscendingByPriority)
|
|
116
|
+
*/
|
|
117
|
+
const nameService = this.owner; //ss[0];
|
|
118
|
+
|
|
119
|
+
console.log(
|
|
120
|
+
"nameService",
|
|
121
|
+
nameService.fullName,
|
|
122
|
+
nameService.domainName,
|
|
123
|
+
nameService.address()
|
|
124
|
+
);
|
|
229
125
|
|
|
230
|
-
|
|
231
|
-
|
|
126
|
+
return [
|
|
127
|
+
DNSRecord(
|
|
128
|
+
"@",
|
|
129
|
+
"SOA",
|
|
130
|
+
dnsFullName(nameService.domainName),
|
|
131
|
+
dnsFullName(this.administratorEmail.replace(/@/, ".")),
|
|
132
|
+
`(${this.soaUpdates.join(" ")})`
|
|
133
|
+
),
|
|
134
|
+
DNSRecord("@", "NS", dnsFullName(nameService.address()))
|
|
135
|
+
];
|
|
232
136
|
}
|
|
233
137
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
138
|
+
async packageContent(outputControl) {
|
|
139
|
+
let hasContent = false;
|
|
237
140
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
141
|
+
if (this.access.length) {
|
|
142
|
+
hasContent ||= await this.generateACLs(outputControl);
|
|
143
|
+
}
|
|
241
144
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
145
|
+
if (this.entries.length) {
|
|
146
|
+
hasContent ||= await this.generateZoneDefs(outputControl, this.entries);
|
|
147
|
+
}
|
|
245
148
|
|
|
246
|
-
|
|
247
|
-
return this._exclude;
|
|
149
|
+
return hasContent;
|
|
248
150
|
}
|
|
249
151
|
|
|
250
|
-
async
|
|
251
|
-
const sources = this.zones.length ? this.zones : [this.owner];
|
|
252
|
-
const names = sources.map(a => a.fullName).join(" ");
|
|
253
|
-
const name = this.owner.owner.name || this.owner.name;
|
|
254
|
-
|
|
255
|
-
const configPackageDir = join(dir, "config") + "/";
|
|
256
|
-
const packageData = {
|
|
257
|
-
outputs: this.outputs,
|
|
258
|
-
sources: [new FileContentProvider(configPackageDir)],
|
|
259
|
-
properties: {
|
|
260
|
-
name: `named-${name}`,
|
|
261
|
-
description: `named definitions for ${names}`,
|
|
262
|
-
access: "private"
|
|
263
|
-
}
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
const forwarders = serviceEndpoints(this.source, {
|
|
267
|
-
services: 'type="dns" && priority>=100 && priority<200',
|
|
268
|
-
endpoints: endpoint => endpoint.family !== "dns",
|
|
269
|
-
select: e => e.address,
|
|
270
|
-
limit: 5
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
if (forwarders.length) {
|
|
274
|
-
await writeLines(
|
|
275
|
-
join(configPackageDir, "etc/named/options"),
|
|
276
|
-
`forwarders.conf`,
|
|
277
|
-
addressesStatement("forwarders", forwarders)
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
|
|
152
|
+
async generateACLs(outputControl) {
|
|
281
153
|
const acls = addressesStatement(
|
|
282
|
-
|
|
283
|
-
addresses(this.
|
|
154
|
+
`acl ${this.name}`,
|
|
155
|
+
addresses(this.access, { aggregate: true })
|
|
284
156
|
);
|
|
285
157
|
|
|
286
|
-
|
|
287
|
-
acls.push(
|
|
288
|
-
...addressesStatement(
|
|
289
|
-
`acl ${view.name}`,
|
|
290
|
-
addresses(view.access, { aggregate: true }),
|
|
291
|
-
true
|
|
292
|
-
)
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if (this.internal?.length) {
|
|
158
|
+
if (acls.length) {
|
|
297
159
|
await writeLines(
|
|
298
|
-
join(
|
|
299
|
-
`0-acl-${name}.conf`,
|
|
160
|
+
join(outputControl.dir, "etc/named"),
|
|
161
|
+
`0-acl-${this.name}.conf`,
|
|
300
162
|
acls
|
|
301
163
|
);
|
|
302
164
|
}
|
|
303
|
-
if (forwarders.length || this.internal?.length) {
|
|
304
|
-
yield packageData;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const ownerAndGroup = { owner: "named", group: "named" };
|
|
308
|
-
const filePermissions = [
|
|
309
|
-
{ ...ownerAndGroup, mode: 0o644 },
|
|
310
|
-
{ ...ownerAndGroup, mode: 0o755 }
|
|
311
|
-
];
|
|
312
|
-
|
|
313
|
-
const zonesPackageDir = join(dir, "zones") + "/";
|
|
314
|
-
|
|
315
|
-
packageData.sources = [
|
|
316
|
-
new FileContentProvider(zonesPackageDir, ...filePermissions)
|
|
317
|
-
];
|
|
318
|
-
packageData.properties = {
|
|
319
|
-
name: `named-zones-${name}`,
|
|
320
|
-
description: `zone definitions for ${names}`,
|
|
321
|
-
dependencies: ["mf-named"],
|
|
322
|
-
access: "private"
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
yield this.generateZoneDefs(newOutputControl(packageData, zonesPackageDir), sources);
|
|
326
|
-
|
|
327
|
-
const location = "outfacing";
|
|
328
|
-
|
|
329
|
-
const outfacingZonesPackageDir = join(dir, location) + "/";
|
|
330
|
-
|
|
331
|
-
packageData.sources = [
|
|
332
|
-
new FileContentProvider(outfacingZonesPackageDir, ...filePermissions)
|
|
333
|
-
];
|
|
334
|
-
packageData.properties = {
|
|
335
|
-
name: `named-zones-${name}-${location}`,
|
|
336
|
-
description: `${location} zone definitions for ${names}`,
|
|
337
|
-
access: "private"
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
yield* this.generateOutfacingDefs(newOutputControl(packageData, outfacingZonesPackageDir), sources);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
async *generateOutfacingDefs(outputControl, sources) {
|
|
344
|
-
for (const source of sources) {
|
|
345
|
-
for (const host of source.hosts()) {
|
|
346
|
-
this.outfacingZones(
|
|
347
|
-
outputControl,
|
|
348
|
-
host,
|
|
349
|
-
this.views.internal,
|
|
350
|
-
this.defaultRecords
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
165
|
|
|
355
|
-
|
|
356
|
-
addHook(
|
|
357
|
-
outputControl.packageData,
|
|
358
|
-
"post_upgrade",
|
|
359
|
-
`/usr/bin/named-hostname-update ${outputControl.configs
|
|
360
|
-
.map(config => config.zones.map(zone => zone.id))
|
|
361
|
-
.flat()
|
|
362
|
-
.join(" ")}`
|
|
363
|
-
);
|
|
364
|
-
|
|
365
|
-
await this.writeZones(outputControl);
|
|
366
|
-
|
|
367
|
-
yield outputControl.packageData;
|
|
368
|
-
}
|
|
166
|
+
return acls.length > 0;
|
|
369
167
|
}
|
|
370
168
|
|
|
371
169
|
async generateZoneDefs(outputControl, sources) {
|
|
372
|
-
const view = this.views.internal;
|
|
373
|
-
|
|
374
170
|
for (const source of sources) {
|
|
375
171
|
console.log(
|
|
376
172
|
"ZONE",
|
|
@@ -383,9 +179,8 @@ export class BindService extends ExtraSourceService {
|
|
|
383
179
|
const reverseZones = new Map();
|
|
384
180
|
|
|
385
181
|
const config = {
|
|
386
|
-
view,
|
|
387
182
|
name: `${domain}.zone.conf`,
|
|
388
|
-
type: this.serverType,
|
|
183
|
+
type: this.service.serverType,
|
|
389
184
|
zones: []
|
|
390
185
|
};
|
|
391
186
|
outputControl.configs.push(config);
|
|
@@ -498,12 +293,6 @@ export class BindService extends ExtraSourceService {
|
|
|
498
293
|
}
|
|
499
294
|
}
|
|
500
295
|
}
|
|
501
|
-
outputControl.configs.push({
|
|
502
|
-
view: this.views.protected,
|
|
503
|
-
inView: this.views.protected.inView,
|
|
504
|
-
name: config.name,
|
|
505
|
-
zones: config.zones
|
|
506
|
-
});
|
|
507
296
|
}
|
|
508
297
|
}
|
|
509
298
|
|
|
@@ -512,77 +301,31 @@ export class BindService extends ExtraSourceService {
|
|
|
512
301
|
return outputControl.packageData;
|
|
513
302
|
}
|
|
514
303
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
domain = domain.substring(2);
|
|
520
|
-
}
|
|
304
|
+
assignCatalog(outputControl, zone, name) {
|
|
305
|
+
if (!this.hasCatalog) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
521
308
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
309
|
+
const directory = dirname(zone.file);
|
|
310
|
+
|
|
311
|
+
let catalogZone = outputControl.catalogs.get(directory);
|
|
312
|
+
|
|
313
|
+
if (!catalogZone) {
|
|
314
|
+
catalogZone = {
|
|
315
|
+
catalog: true,
|
|
316
|
+
id: `catalog.${name}`,
|
|
317
|
+
file: `${directory}/catalog.${name}.zone`,
|
|
318
|
+
records: new Set([
|
|
319
|
+
...this.defaultRecords,
|
|
320
|
+
DNSRecord("version", "TXT", '"2"')
|
|
321
|
+
])
|
|
526
322
|
};
|
|
323
|
+
outputControl.catalogs.set(directory, catalogZone);
|
|
324
|
+
|
|
527
325
|
const config = {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
zones: [zone]
|
|
532
|
-
};
|
|
533
|
-
zone.config = config;
|
|
534
|
-
outputControl.configs.push(config);
|
|
535
|
-
|
|
536
|
-
if (this.hasLocationRecord) {
|
|
537
|
-
zone.records.add(DNSRecord("location", "TXT", host.location.name));
|
|
538
|
-
}
|
|
539
|
-
for (const na of host.networkAddresses(
|
|
540
|
-
na => na.networkInterface.kind !== "loopback"
|
|
541
|
-
)) {
|
|
542
|
-
zone.records.add(
|
|
543
|
-
DNSRecord("@", dnsRecordTypeForAddressFamily(na.family), na.address)
|
|
544
|
-
);
|
|
545
|
-
|
|
546
|
-
if (wildcard) {
|
|
547
|
-
zone.records.add(
|
|
548
|
-
DNSRecord("*", dnsRecordTypeForAddressFamily(na.family), na.address)
|
|
549
|
-
);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
this.assignCatalog(
|
|
554
|
-
outputControl,
|
|
555
|
-
zone,
|
|
556
|
-
`outfacting.${host.location.name}`
|
|
557
|
-
);
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
assignCatalog(outputControl, zone, name) {
|
|
562
|
-
if (!this.hasCatalog) {
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
const directory = dirname(zone.file);
|
|
567
|
-
|
|
568
|
-
let catalogZone = outputControl.catalogs.get(directory);
|
|
569
|
-
|
|
570
|
-
if (!catalogZone) {
|
|
571
|
-
catalogZone = {
|
|
572
|
-
catalog: true,
|
|
573
|
-
id: `catalog.${name}`,
|
|
574
|
-
file: `${directory}/catalog.${name}.zone`,
|
|
575
|
-
records: new Set([
|
|
576
|
-
...this.defaultRecords,
|
|
577
|
-
DNSRecord("version", "TXT", '"2"')
|
|
578
|
-
])
|
|
579
|
-
};
|
|
580
|
-
outputControl.catalogs.set(directory, catalogZone);
|
|
581
|
-
const config = {
|
|
582
|
-
view: zone.config.view,
|
|
583
|
-
name: `catalog.${name}.zone.conf`,
|
|
584
|
-
type: this.serverType,
|
|
585
|
-
zones: [catalogZone]
|
|
326
|
+
name: `catalog.${name}.zone.conf`,
|
|
327
|
+
type: this.service.serverType,
|
|
328
|
+
zones: [catalogZone]
|
|
586
329
|
};
|
|
587
330
|
catalogZone.config = config;
|
|
588
331
|
outputControl.configs.push(config);
|
|
@@ -597,25 +340,9 @@ export class BindService extends ExtraSourceService {
|
|
|
597
340
|
return catalogZone;
|
|
598
341
|
}
|
|
599
342
|
|
|
600
|
-
get defaultRecords() {
|
|
601
|
-
const nameService = this.findService('in("dns",types) && priority>=300');
|
|
602
|
-
|
|
603
|
-
const SOARecord = DNSRecord(
|
|
604
|
-
"@",
|
|
605
|
-
"SOA",
|
|
606
|
-
dnsFullName(nameService.domainName),
|
|
607
|
-
dnsFullName(this.administratorEmail.replace(/@/, ".")),
|
|
608
|
-
`(${[...this.soaUpdates].join(" ")})`
|
|
609
|
-
);
|
|
610
|
-
|
|
611
|
-
const NSRecord = DNSRecord("@", "NS", dnsFullName(nameService.address()));
|
|
612
|
-
|
|
613
|
-
return [SOARecord, NSRecord];
|
|
614
|
-
}
|
|
615
|
-
|
|
616
343
|
async writeZones(outputControl) {
|
|
617
344
|
for (const config of outputControl.configs) {
|
|
618
|
-
console.log(`config: ${
|
|
345
|
+
console.log(`config: ${this.name}/${config.name}`);
|
|
619
346
|
|
|
620
347
|
const content = [];
|
|
621
348
|
|
|
@@ -624,8 +351,8 @@ export class BindService extends ExtraSourceService {
|
|
|
624
351
|
|
|
625
352
|
content.push(`zone \"${zone.id}\" {`);
|
|
626
353
|
|
|
627
|
-
if (
|
|
628
|
-
content.push(` in-view ${
|
|
354
|
+
if (this.sharedWith) {
|
|
355
|
+
content.push(` in-view ${this.sharedWith.name};`);
|
|
629
356
|
} else {
|
|
630
357
|
content.push(` type ${config.type};`);
|
|
631
358
|
content.push(` file \"${zone.file}\";`);
|
|
@@ -657,7 +384,7 @@ export class BindService extends ExtraSourceService {
|
|
|
657
384
|
}
|
|
658
385
|
|
|
659
386
|
await writeLines(
|
|
660
|
-
join(outputControl.dir, `etc/named/${
|
|
387
|
+
join(outputControl.dir, `etc/named/${this.name}`),
|
|
661
388
|
config.name,
|
|
662
389
|
content
|
|
663
390
|
);
|
|
@@ -665,6 +392,315 @@ export class BindService extends ExtraSourceService {
|
|
|
665
392
|
}
|
|
666
393
|
}
|
|
667
394
|
|
|
395
|
+
const BindServiceTypeDefinition = {
|
|
396
|
+
name: "bind",
|
|
397
|
+
extends: ExtraSourceServiceTypeDefinition,
|
|
398
|
+
specializationOf: ServiceTypeDefinition,
|
|
399
|
+
owners: ServiceTypeDefinition.owners,
|
|
400
|
+
key: "name",
|
|
401
|
+
attributes: {
|
|
402
|
+
groups: {
|
|
403
|
+
...default_attribute_writable,
|
|
404
|
+
type: BindGroupTypeDefinition,
|
|
405
|
+
collection: true,
|
|
406
|
+
writable: true
|
|
407
|
+
},
|
|
408
|
+
primaries: {
|
|
409
|
+
...default_attribute_writable,
|
|
410
|
+
type: networkAddressType,
|
|
411
|
+
collection: true
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
service: {
|
|
415
|
+
systemdService: "bind.service",
|
|
416
|
+
extends: ["dns"],
|
|
417
|
+
services: {
|
|
418
|
+
"bind-statistics": {
|
|
419
|
+
endpoints: [
|
|
420
|
+
{
|
|
421
|
+
family: "IPv4",
|
|
422
|
+
port: 19521,
|
|
423
|
+
protocol: "tcp",
|
|
424
|
+
pathname: "/",
|
|
425
|
+
tls: false,
|
|
426
|
+
kind: "loopback"
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
family: "IPv6",
|
|
430
|
+
port: 19521,
|
|
431
|
+
protocol: "tcp",
|
|
432
|
+
pathname: "/",
|
|
433
|
+
tls: false,
|
|
434
|
+
kind: "loopback"
|
|
435
|
+
}
|
|
436
|
+
]
|
|
437
|
+
},
|
|
438
|
+
"bind-rdnc": {
|
|
439
|
+
endpoints: [
|
|
440
|
+
{
|
|
441
|
+
family: "IPv4",
|
|
442
|
+
port: 953,
|
|
443
|
+
protocol: "tcp",
|
|
444
|
+
tls: false,
|
|
445
|
+
kind: "loopback"
|
|
446
|
+
}
|
|
447
|
+
]
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
function addressesStatement(prefix, objects, generateEmpty = false) {
|
|
454
|
+
const body = asArray(objects).map(name => ` ${name};`);
|
|
455
|
+
|
|
456
|
+
if (body.length || generateEmpty) {
|
|
457
|
+
return [`${prefix} {`, body, "};"];
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return [];
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export class BindService extends ExtraSourceService {
|
|
464
|
+
static typeDefinition = BindServiceTypeDefinition;
|
|
465
|
+
|
|
466
|
+
static {
|
|
467
|
+
addType(this);
|
|
468
|
+
addServiceType(this.typeDefinition.service, this.typeDefinition.name);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
groups = {};
|
|
472
|
+
|
|
473
|
+
get type() {
|
|
474
|
+
return BindServiceTypeDefinition.name;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
materializeExtends() {
|
|
478
|
+
super.materializeExtends();
|
|
479
|
+
|
|
480
|
+
//console.log("ME", this.fullName, this.extends);
|
|
481
|
+
for (const service of this.walkDirections(["extends"])) {
|
|
482
|
+
console.log(
|
|
483
|
+
"BindService materializeExtends",
|
|
484
|
+
this.fullName,
|
|
485
|
+
service.fullName
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
for (const group of Object.values(service.groups)) {
|
|
489
|
+
const present = this.groups[group.name];
|
|
490
|
+
|
|
491
|
+
if (present) {
|
|
492
|
+
//console.log("LINK", present.fullName, group.fullName);
|
|
493
|
+
present.extends.push(group);
|
|
494
|
+
} else {
|
|
495
|
+
this.groups[group.name] = group.forOwner(this);
|
|
496
|
+
|
|
497
|
+
console.log(
|
|
498
|
+
group.fullName,
|
|
499
|
+
this.groups[group.name].entries.map(e => e.fullName)
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/*
|
|
504
|
+
console.log(
|
|
505
|
+
eg.fullName,
|
|
506
|
+
eg.entries.map(e => e.fullName)
|
|
507
|
+
);*/
|
|
508
|
+
//console.log("EXTENDS", this.fullName, service.fullName, eg.fullName, eg.owner.fullName);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
_traverse(...args) {
|
|
514
|
+
if (super._traverse(...args)) {
|
|
515
|
+
for (const group of Object.values(this.groups)) {
|
|
516
|
+
group._traverse(...args);
|
|
517
|
+
}
|
|
518
|
+
return true;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
typeNamed(type, name) {
|
|
525
|
+
if (type === BindGroupTypeDefinition.name) {
|
|
526
|
+
return this.groups[name];
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
return super.typeNamed(type, name);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
get serverType() {
|
|
533
|
+
return this.primaries ? "secondary" : "primary";
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
async writeForwarders(outputControl) {
|
|
537
|
+
const forwarders = serviceEndpoints(this.source, {
|
|
538
|
+
services: 'services[types[dns]" && priority>=100 && priority<200]',
|
|
539
|
+
endpoints: endpoint => endpoint.family !== "dns",
|
|
540
|
+
select: e => e.address,
|
|
541
|
+
limit: 5
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
if (forwarders.length) {
|
|
545
|
+
await writeLines(
|
|
546
|
+
join(outputControl.dir, "etc/named/options"),
|
|
547
|
+
`forwarders.conf`,
|
|
548
|
+
addressesStatement("forwarders", forwarders)
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
return forwarders.length > 0;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
async *preparePackages(dir) {
|
|
556
|
+
const basePackageDir = dir;
|
|
557
|
+
const packageData = this.packageData;
|
|
558
|
+
packageData.sources.push(new FileContentProvider(basePackageDir));
|
|
559
|
+
|
|
560
|
+
const outputControl = newOutputControl(packageData, basePackageDir);
|
|
561
|
+
|
|
562
|
+
let hasContent = false;
|
|
563
|
+
|
|
564
|
+
console.log("PAKAGE", Object.keys(this.groups));
|
|
565
|
+
|
|
566
|
+
for (const group of Object.values(this.groups)) {
|
|
567
|
+
hasContent ||= await group.packageContent(outputControl);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
hasContent ||= await this.writeForwarders(outputControl);
|
|
571
|
+
|
|
572
|
+
if (hasContent) {
|
|
573
|
+
yield packageData;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/*
|
|
577
|
+
const sources = this.zones.length ? this.zones : [this.owner];
|
|
578
|
+
const names = sources.map(a => a.fullName).join(" ");
|
|
579
|
+
const name = this.owner.owner.name || this.owner.name;
|
|
580
|
+
|
|
581
|
+
Object.assign(packageData.properties, {
|
|
582
|
+
name: `named-${name}`,
|
|
583
|
+
description: `named definitions for ${names}`
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
const ownerAndGroup = { owner: "named", group: "named" };
|
|
587
|
+
const filePermissions = [
|
|
588
|
+
{ ...ownerAndGroup, mode: 0o644 },
|
|
589
|
+
{ ...ownerAndGroup, mode: 0o755 }
|
|
590
|
+
];
|
|
591
|
+
|
|
592
|
+
const zonesPackageDir = join(dir, "zones") + "/";
|
|
593
|
+
|
|
594
|
+
packageData.sources = [
|
|
595
|
+
new FileContentProvider(zonesPackageDir, ...filePermissions)
|
|
596
|
+
];
|
|
597
|
+
packageData.properties = {
|
|
598
|
+
name: `named-zones-${name}`,
|
|
599
|
+
description: `zone definitions for ${names}`,
|
|
600
|
+
dependencies: ["mf-named"],
|
|
601
|
+
access: "private"
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
yield this.generateZoneDefs(
|
|
605
|
+
newOutputControl(packageData, zonesPackageDir),
|
|
606
|
+
sources
|
|
607
|
+
);
|
|
608
|
+
|
|
609
|
+
const location = "outfacing";
|
|
610
|
+
|
|
611
|
+
const outfacingZonesPackageDir = join(dir, location) + "/";
|
|
612
|
+
|
|
613
|
+
packageData.sources = [
|
|
614
|
+
new FileContentProvider(outfacingZonesPackageDir, ...filePermissions)
|
|
615
|
+
];
|
|
616
|
+
packageData.properties = {
|
|
617
|
+
name: `named-zones-${name}-${location}`,
|
|
618
|
+
description: `${location} zone definitions for ${names}`,
|
|
619
|
+
access: "private"
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
yield* this.generateOutfacingDefs(
|
|
623
|
+
newOutputControl(packageData, outfacingZonesPackageDir),
|
|
624
|
+
sources
|
|
625
|
+
);
|
|
626
|
+
*/
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
async *generateOutfacingDefs(outputControl, sources) {
|
|
630
|
+
for (const source of sources) {
|
|
631
|
+
for (const host of source.hosts) {
|
|
632
|
+
this.outfacingZones(
|
|
633
|
+
outputControl,
|
|
634
|
+
host,
|
|
635
|
+
this.groups.internal,
|
|
636
|
+
this.defaultRecords
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
if (outputControl.configs.length) {
|
|
642
|
+
addHook(
|
|
643
|
+
outputControl.packageData,
|
|
644
|
+
"post_upgrade",
|
|
645
|
+
`/usr/bin/named-hostname-update ${outputControl.configs
|
|
646
|
+
.map(config => config.zones.map(zone => zone.id))
|
|
647
|
+
.flat()
|
|
648
|
+
.join(" ")}`
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
await this.writeZones(outputControl);
|
|
652
|
+
|
|
653
|
+
yield outputControl.packageData;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
outfacingZones(outputControl, host, group, records) {
|
|
658
|
+
host.foreignDomainNames.map(domain => {
|
|
659
|
+
const wildcard = domain.startsWith("*.");
|
|
660
|
+
if (wildcard) {
|
|
661
|
+
domain = domain.substring(2);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
const zone = {
|
|
665
|
+
id: domain,
|
|
666
|
+
file: `${host.location.name}/outfacing/${domain}.zone`,
|
|
667
|
+
records: new Set(records)
|
|
668
|
+
};
|
|
669
|
+
const config = {
|
|
670
|
+
group,
|
|
671
|
+
name: `${domain}.zone.conf`,
|
|
672
|
+
type: this.serverType,
|
|
673
|
+
zones: [zone]
|
|
674
|
+
};
|
|
675
|
+
zone.config = config;
|
|
676
|
+
outputControl.configs.push(config);
|
|
677
|
+
|
|
678
|
+
if (this.hasLocationRecord) {
|
|
679
|
+
zone.records.add(DNSRecord("location", "TXT", host.location.name));
|
|
680
|
+
}
|
|
681
|
+
for (const na of host.networkAddresses(
|
|
682
|
+
na => na.networkInterface.kind !== "loopback"
|
|
683
|
+
)) {
|
|
684
|
+
zone.records.add(
|
|
685
|
+
DNSRecord("@", dnsRecordTypeForAddressFamily(na.family), na.address)
|
|
686
|
+
);
|
|
687
|
+
|
|
688
|
+
if (wildcard) {
|
|
689
|
+
zone.records.add(
|
|
690
|
+
DNSRecord("*", dnsRecordTypeForAddressFamily(na.family), na.address)
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
this.assignCatalog(
|
|
696
|
+
outputControl,
|
|
697
|
+
zone,
|
|
698
|
+
`outfacting.${host.location.name}`
|
|
699
|
+
);
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
668
704
|
function newOutputControl(packageData, dir) {
|
|
669
705
|
return { configs: [], catalogs: new Map(), packageData, dir };
|
|
670
706
|
}
|