-
Notifications
You must be signed in to change notification settings - Fork 32
/
Powerdns.php
365 lines (315 loc) · 10.2 KB
/
Powerdns.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
<?php
namespace Exonet\Powerdns;
use Exonet\Powerdns\Resources\SearchResult;
use Exonet\Powerdns\Resources\SearchResultSet;
use Exonet\Powerdns\Resources\Zone as ZoneResource;
use Exonet\Powerdns\Transformers\CreateZoneTransformer;
use LogicException;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
class Powerdns implements PowerdnsInterface
{
/**
* The version of this package. This is being used for the user-agent header.
*/
public const CLIENT_VERSION = 'v4.6.0';
/**
* @var Powerdns The client instance.
*/
private static $_instance;
/**
* @var LoggerInterface The logger instance.
*/
private $logger;
/**
* @var string The PowerDNS host. Must include protocol (http, https, etc.).
*/
private $host;
/**
* @var int The PowerDNS API Port.
*/
private $port = 8081;
/**
* @var string The PowerDNS API key.
*/
private $apiKey;
/**
* @var string The PowerDNS server to use.
*/
private $server = 'localhost';
/**
* @var ConnectorInterface The PowerDNS Connector to make calls.
*/
private $connector;
/**
* PowerDNS Client constructor.
*
* @param string|null $host (optional) The PowerDNS host. Must include protocol (http, https, etc.).
* @param string|null $apiKey (optional) The PowerDNS API key.
* @param int|null $port (optional) The PowerDNS API Port.
* @param string|null $server (optional) The PowerDNS server to use.
* @param ConnectorInterface|null $connector (optional) The Connector to make calls.
*/
public function __construct(
?string $host = null,
?string $apiKey = null,
?int $port = null,
?string $server = null,
?ConnectorInterface $connector = null
) {
if (self::$_instance === null) {
self::$_instance = $this;
}
if ($host !== null) {
$this->host = $host;
}
if ($apiKey !== null) {
$this->apiKey = $apiKey;
}
if ($port !== null) {
$this->port = $port;
}
if ($server !== null) {
$this->server = $server;
}
$this->connector = $connector ?? new Connector($this);
}
/**
* Set the configured connector instance instead of the default one.
*
* @param ConnectorInterface $connector The connector instance to use.
*
* @return $this The current Powerdns class.
*/
public function setConnector(ConnectorInterface $connector): self
{
$this->connector = $connector;
return $this;
}
/**
* Configure a new connection to a PowerDNS server.
*
* @param string $host The PowerDNS host. Must include protocol (http, https, etc.).
* @param int $port The PowerDNS API Port.
* @param string $server The PowerDNS server to use.
*
* @return PowerdnsInterface The created PowerDNS client.
*/
public function connect(string $host, int $port = 8081, string $server = 'localhost'): PowerdnsInterface
{
$this->host = $host;
$this->port = $port;
$this->server = $server;
return $this;
}
/**
* Set the authorization key to use for each request.
*
* @param string $key The key to use.
*
* @return PowerdnsInterface The current client.
*/
public function useKey(string $key): PowerdnsInterface
{
$this->apiKey = $key;
return $this;
}
/**
* Create a new zone.
*
* @param string $canonicalDomain The canonical domain name.
* @param array $nameservers The name servers.
* @param bool $useDnssec (Default: false) When true use DNSSEC for this zone.
*
* @return Zone The created Zone.
*/
public function createZone(string $canonicalDomain, array $nameservers, bool $useDnssec = false): Zone
{
$fixDot = substr($canonicalDomain, -1) !== '.';
if ($fixDot) {
$canonicalDomain .= '.';
}
$newZone = new ZoneResource();
$newZone->setName($canonicalDomain);
$newZone->setNameservers($nameservers);
$newZone->setDnssec($useDnssec);
$postData = new CreateZoneTransformer($newZone);
$this->connector->post('zones', $postData);
return $this->zone($canonicalDomain);
}
/**
* Create a new zone based on a zone resource.
*
* @param ZoneResource $zoneResource The zone resource.
*
* @return Zone The created zone.
*/
public function createZoneFromResource(ZoneResource $zoneResource): Zone
{
$this->connector->post('zones', new CreateZoneTransformer($zoneResource));
return $this->zone($zoneResource->getName());
}
/**
* Get a zone instance to work with.
*
* @param string $canonicalDomain The canonical domain name of the zone.
*
* @return Zone The zone.
*/
public function zone(string $canonicalDomain): Zone
{
return new Zone($this->connector, $canonicalDomain);
}
/**
* Remove a zone.
*
* @param string $canonicalDomain The canonical domain name of the zone to remove.
*
* @return bool True that the zone was removed.
*/
public function deleteZone(string $canonicalDomain): bool
{
$this->connector->delete('zones/'.$canonicalDomain);
return true;
}
/**
* Retrieve all zones.
*
* @param bool $includeDnssecAndEditedSerialFields If 'true' then dnssec and edited_serial are included.
*
* @return Zone[] Array containing the zones
*
* @see https://doc.powerdns.com/authoritative/http-api/zone.html#get--servers-server_id-zones
*/
public function listZones(bool $includeDnssecAndEditedSerialFields = false): array
{
return array_map(
function (array $args) {
return new Zone($this->connector, $args['id']);
},
$this->connector->get('zones?dnssec='.($includeDnssecAndEditedSerialFields ? 'true' : 'false'))
);
}
/**
* Get a cryptokey instance to work with.
*
* @param string $canonicalDomain The canonical domain name of the zone.
*
* @return Cryptokey The cryptokey instance.
*/
public function cryptokeys(string $canonicalDomain): Cryptokey
{
return new Cryptokey($this->connector, $canonicalDomain);
}
/**
* Get a TSIGKey instance to work with.
*
* @return TSIGKey The TSIGKey instance
*/
public function tsigkeys(): TSIGKey
{
return new TSIGKey($this->connector);
}
/**
* Query PowerDNS internal statistics.
* The ring statistics are disabled by default to speedup the request and reduce the response size.
*
* The $statistics and $includeRings parameters are supported in PowerDNS 4.3 and newer.
* On older PowerDNS instances these parameters are ignored.
*
* @param string|null $statistic Optional name of a specific statistic to get.
* @param bool $includeRings Include ring statistics or not.
*
* @return array An array with statistics.
*/
public function statistics($statistic = null, $includeRings = false): array
{
// Convert $includeRings param to string.
$includeRings = $includeRings ? 'true' : 'false';
$endpoint = 'statistics?includerings='.$includeRings;
// Request a specific statistic.
if ($statistic) {
$endpoint .= '&statistic='.$statistic;
}
return $this->connector->get($endpoint);
}
/**
* Search for the specified string in zones, records, comments or in all three. The * character can be used in the
* query as a wildcard character and the ? character can be used as a wildcard for a single character.
*
* @param string $query The string to search for.
* @param int $size The maximum number of returned results.
* @param string $type The search type. Can be 'all', 'zone', 'record' or 'comment'.
*
* @return SearchResultSet A collection with search results.
*/
public function search(string $query, int $size = 100, string $type = 'all'): SearchResultSet
{
if (!in_array($type, ['all', 'zone', 'record', 'comment'])) {
throw new LogicException('Invalid search type given. Type must be one of "all", "zone", "record" or "comment".');
}
if ($size < 1) {
throw new LogicException('Invalid search size given. Must be at least 1.');
}
$response = $this->connector->get(
sprintf(
'search-data?q=%s&max=%d&object_type=%s',
urlencode($query),
$size,
$type
)
);
$searchResults = array_map(static function ($item) {
return new SearchResult($item);
}, $response);
return new SearchResultSet($searchResults);
}
/**
* Get the PowerDNS server version.
*
* @return string The server version.
*/
public function serverVersion(): string
{
return $this->connector->get('/')['version'];
}
/**
* Get the logger instance.
*
* @return LoggerInterface The log instance.
*/
public function log(): LoggerInterface
{
if ($this->logger === null) {
// If there's no logger set, use the NullLogger.
$this->logger = new NullLogger();
}
return $this->logger;
}
/**
* Set the logger instance to use.
*
* @param LoggerInterface $log The log instance to use.
*
* @return PowerdnsInterface The current client instance.
*/
public function setLogger(LoggerInterface $log): PowerdnsInterface
{
$this->logger = $log;
return $this;
}
/**
* Get the client config items.
*
* @return mixed[] Array containing the client config items.
*/
public function getConfig(): array
{
return [
'host' => $this->host,
'port' => $this->port,
'server' => $this->server,
'apiKey' => $this->apiKey,
];
}
}