From 388e9743f63f5a02b9f571cab88508acf7c6a86d Mon Sep 17 00:00:00 2001 From: Bennet Gallein Date: Sat, 11 May 2024 21:46:30 +0200 Subject: [PATCH] feat: add tsig api --- src/Powerdns.php | 78 ++++++------ src/Resources/TSIGKey.php | 163 ++++++++++++++++++++++++ src/Resources/TSIGKeySet.php | 135 ++++++++++++++++++++ src/TSIGKey.php | 67 ++++++++++ src/TSIGKeyAlgorithms.php | 19 +++ src/Transformers/TSIGKeyTransformer.php | 18 +++ 6 files changed, 439 insertions(+), 41 deletions(-) create mode 100644 src/Resources/TSIGKey.php create mode 100644 src/Resources/TSIGKeySet.php create mode 100644 src/TSIGKey.php create mode 100644 src/TSIGKeyAlgorithms.php create mode 100644 src/Transformers/TSIGKeyTransformer.php diff --git a/src/Powerdns.php b/src/Powerdns.php index 94813bb..049ce34 100644 --- a/src/Powerdns.php +++ b/src/Powerdns.php @@ -10,8 +10,7 @@ use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; -class Powerdns implements PowerdnsInterface -{ +class Powerdns implements PowerdnsInterface { /** * The version of this package. This is being used for the user-agent header. */ @@ -98,8 +97,7 @@ public function __construct( * * @return $this The current Powerdns class. */ - public function setConnector(ConnectorInterface $connector): self - { + public function setConnector(ConnectorInterface $connector): self { $this->connector = $connector; return $this; @@ -114,10 +112,9 @@ public function setConnector(ConnectorInterface $connector): self * * @return PowerdnsInterface The created PowerDNS client. */ - public function connect(string $host, int $port = 8081, string $server = 'localhost'): PowerdnsInterface - { - $this->host = $host; - $this->port = $port; + public function connect(string $host, int $port = 8081, string $server = 'localhost'): PowerdnsInterface { + $this->host = $host; + $this->port = $port; $this->server = $server; return $this; @@ -130,8 +127,7 @@ public function connect(string $host, int $port = 8081, string $server = 'localh * * @return PowerdnsInterface The current client. */ - public function useKey(string $key): PowerdnsInterface - { + public function useKey(string $key): PowerdnsInterface { $this->apiKey = $key; return $this; @@ -146,8 +142,7 @@ public function useKey(string $key): PowerdnsInterface * * @return Zone The created Zone. */ - public function createZone(string $canonicalDomain, array $nameservers, bool $useDnssec = false): Zone - { + public function createZone(string $canonicalDomain, array $nameservers, bool $useDnssec = false): Zone { $fixDot = substr($canonicalDomain, -1) !== '.'; if ($fixDot) { @@ -172,8 +167,7 @@ public function createZone(string $canonicalDomain, array $nameservers, bool $us * * @return Zone The created zone. */ - public function createZoneFromResource(ZoneResource $zoneResource): Zone - { + public function createZoneFromResource(ZoneResource $zoneResource): Zone { $this->connector->post('zones', new CreateZoneTransformer($zoneResource)); return $this->zone($zoneResource->getName()); @@ -186,8 +180,7 @@ public function createZoneFromResource(ZoneResource $zoneResource): Zone * * @return Zone The zone. */ - public function zone(string $canonicalDomain): Zone - { + public function zone(string $canonicalDomain): Zone { return new Zone($this->connector, $canonicalDomain); } @@ -198,9 +191,8 @@ public function zone(string $canonicalDomain): Zone * * @return bool True that the zone was removed. */ - public function deleteZone(string $canonicalDomain): bool - { - $this->connector->delete('zones/'.$canonicalDomain); + public function deleteZone(string $canonicalDomain): bool { + $this->connector->delete('zones/' . $canonicalDomain); return true; } @@ -214,13 +206,12 @@ public function deleteZone(string $canonicalDomain): bool * * @see https://doc.powerdns.com/authoritative/http-api/zone.html#get--servers-server_id-zones */ - public function listZones(bool $includeDnssecAndEditedSerialFields = false): array - { + 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')) + $this->connector->get('zones?dnssec=' . ($includeDnssecAndEditedSerialFields ? 'true' : 'false')) ); } @@ -231,11 +222,20 @@ function (array $args) { * * @return Cryptokey The cryptokey instance. */ - public function cryptokeys(string $canonicalDomain): Cryptokey - { + 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. @@ -248,16 +248,15 @@ public function cryptokeys(string $canonicalDomain): Cryptokey * * @return array An array with statistics. */ - public function statistics($statistic = null, $includeRings = false): array - { + public function statistics($statistic = null, $includeRings = false): array { // Convert $includeRings param to string. $includeRings = $includeRings ? 'true' : 'false'; - $endpoint = 'statistics?includerings='.$includeRings; + $endpoint = 'statistics?includerings=' . $includeRings; // Request a specific statistic. if ($statistic) { - $endpoint .= '&statistic='.$statistic; + $endpoint .= '&statistic=' . $statistic; } return $this->connector->get($endpoint); @@ -273,8 +272,7 @@ public function statistics($statistic = null, $includeRings = false): array * * @return SearchResultSet A collection with search results. */ - public function search(string $query, int $size = 100, string $type = 'all'): SearchResultSet - { + 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".'); } @@ -292,7 +290,9 @@ public function search(string $query, int $size = 100, string $type = 'all'): Se ) ); - $searchResults = array_map(static function ($item) { return new SearchResult($item); }, $response); + $searchResults = array_map(static function ($item) { + return new SearchResult($item); + }, $response); return new SearchResultSet($searchResults); } @@ -302,8 +302,7 @@ public function search(string $query, int $size = 100, string $type = 'all'): Se * * @return string The server version. */ - public function serverVersion(): string - { + public function serverVersion(): string { return $this->connector->get('/')['version']; } @@ -312,8 +311,7 @@ public function serverVersion(): string * * @return LoggerInterface The log instance. */ - public function log(): LoggerInterface - { + public function log(): LoggerInterface { if ($this->logger === null) { // If there's no logger set, use the NullLogger. $this->logger = new NullLogger(); @@ -329,8 +327,7 @@ public function log(): LoggerInterface * * @return PowerdnsInterface The current client instance. */ - public function setLogger(LoggerInterface $log): PowerdnsInterface - { + public function setLogger(LoggerInterface $log): PowerdnsInterface { $this->logger = $log; return $this; @@ -341,11 +338,10 @@ public function setLogger(LoggerInterface $log): PowerdnsInterface * * @return mixed[] Array containing the client config items. */ - public function getConfig(): array - { + public function getConfig(): array { return [ - 'host' => $this->host, - 'port' => $this->port, + 'host' => $this->host, + 'port' => $this->port, 'server' => $this->server, 'apiKey' => $this->apiKey, ]; diff --git a/src/Resources/TSIGKey.php b/src/Resources/TSIGKey.php new file mode 100644 index 0000000..01a0dfd --- /dev/null +++ b/src/Resources/TSIGKey.php @@ -0,0 +1,163 @@ +setName($content['name'] ?? ""); + $this->setId($content['id'] ?? ""); + $this->setAlgorithm($content['algorithm'] ?? ""); + $this->setKey($content['key'] ?? ""); + $this->setType($content['type'] ?? ""); + } + } + + /** + * Get set to "TSIGKey" + * + * @return string + */ + public function getType() { + return $this->type; + } + + /** + * Set set to "TSIGKey" + * + * @param string $type Set to "TSIGKey" + * + * @return self + */ + public function setType(string $type) { + $this->type = $type; + + return $this; + } + + /** + * Get the Base64 encoded secret key, empty when listing keys. MAY be empty when POSTing to have the server generate the key material + * + * @return string + */ + public function getKey() { + return $this->key; + } + + /** + * Set the Base64 encoded secret key, empty when listing keys. MAY be empty when POSTing to have the server generate the key material + * + * @param string $key The Base64 encoded secret key, empty when listing keys. MAY be empty when POSTing to have the server generate the key material + * + * @return self + */ + public function setKey(string $key) { + $this->key = $key; + + return $this; + } + + /** + * Get the algorithm of the TSIG key + * + * @return string + */ + public function getAlgorithm() { + return $this->algorithm; + } + + /** + * Set the algorithm of the TSIG key + * + * @param string $algorithm The algorithm of the TSIG key + * + * @return self + */ + public function setAlgorithm(string $algorithm) { + $this->algorithm = $algorithm; + + return $this; + } + + /** + * Get the ID for this key, used in the TSIGkey URL endpoint. + * + * @return string + */ + public function getId() { + return $this->id; + } + + /** + * Set the ID for this key, used in the TSIGkey URL endpoint. + * + * @param string $id The ID for this key, used in the TSIGkey URL endpoint. + * + * @return self + */ + public function setId(string $id) { + $this->id = $id; + + return $this; + } + + /** + * Get the name of the key + * + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * Set the name of the key + * + * @param string $name The name of the key + * + * @return self + */ + public function setName(string $name) { + $this->name = $name; + + return $this; + } +} diff --git a/src/Resources/TSIGKeySet.php b/src/Resources/TSIGKeySet.php new file mode 100644 index 0000000..a82ad57 --- /dev/null +++ b/src/Resources/TSIGKeySet.php @@ -0,0 +1,135 @@ +tsigResources = $resourceRecords; + } + } + + /** + * Add a single tsigkey resource to the existing collection. + * + * @param TSIGKey $metaResource The tsigkey resource to add. + * + * @return TSIGKeySet The current TSIGKeySet instance. + */ + public function addResource(TSIGKey $metaResource): self { + $this->tsigResources[] = $metaResource; + + return $this; + } + + /** + * Get the number of tsigkey resources in this collection. + * + * @return int The number of tsigkey resources. + */ + public function count(): int { + return count($this->tsigResources); + } + + /** + * Check if the current collection is not empty. + * + * @return bool True when there are tsigkey resources in this collection. + */ + public function isNotEmpty(): bool { + return !$this->isEmpty(); + } + + /** + * Check if the current collection is empty. + * + * @return bool True when there are no tsigkey resources in this collection. + */ + public function isEmpty(): bool { + return empty($this->tsigResources); + } + + /** + * Loop through the collection and call the given closure for each tsigkey resource. + * + * @param Closure $closure The closure to execute for each tsigkey resource. + * + * @return TSIGKeySet The current TSIGKeySet instance. + */ + public function map(Closure $closure): self { + foreach ($this->tsigResources as $index => $resource) { + $this->tsigResources[$index] = $closure($resource, $index); + } + + return $this; + } + + /** + * Delete all tsigkey resources that are set in the current collection. + * + * @return bool True when the tsigkey resources are deleted. + */ + public function delete(): bool { + foreach ($this->tsigResources as $resource) { + $resource->delete(); + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function getIterator(): ArrayIterator { + return new ArrayIterator($this->tsigResources); + } + + /** + * {@inheritdoc} + */ + public function offsetExists($offset): bool { + return isset($this->tsigResources[$offset]); + } + + /** + * {@inheritdoc} + * + * @return TSIGKey + */ + #[ReturnTypeWillChange] + public function offsetGet($offset) { + return $this->tsigResources[$offset]; + } + + /** + * {@inheritdoc} + */ + public function offsetSet($offset, $value): void { + $this->tsigResources[$offset] = $value; + } + + /** + * {@inheritdoc} + */ + public function offsetUnset($offset): void { + unset($this->tsigResources[$offset]); + } +} diff --git a/src/TSIGKey.php b/src/TSIGKey.php new file mode 100644 index 0000000..318fe11 --- /dev/null +++ b/src/TSIGKey.php @@ -0,0 +1,67 @@ +connector->get('tsigkeys'); + + $resultSet = new TSIGKeySet(); + foreach ($items as $item) { + $resultSet->addResource(new TSIGKeyResource($item)); + } + + return $resultSet; + } + + /** + * Creat a new TSIG Key + * + * @param array|string $data The data. + * + * @return TSIGKeySet The created key data set. + */ + public function create(TSIGKeyResource $data): TSIGKeySet { + $response = $this->connector->post('tsigkeys', new TSIGKeyTransformer($data)); + + return new TSIGKeySet([new TSIGKeyResource($response)]); + } + + /** + * Update an existing tsig key. + * + * @param TSIGKeyResource $key The key data item to update. + * + * @return bool True if the update was successful. + */ + public function update(TSIGKeyResource $key): bool { + $response = $this->connector->put('tsigkeys/' . $key->getId(), new TSIGKeyTransformer($key)); + + // If the response is empty, everything is fine. + return empty($response); + } + + /** + * Delete an existing tsigkey item. + * + * @param TSIGKeyResource $key The tsigkey data item to delete. + * + * @return bool True if the delete was successful. + */ + public function delete(TSIGKeyResource $key): bool { + $response = $this->connector->delete('tsigkeys/' . $key->getId()); + + // If the response is empty, everything is fine. + return empty($response); + } +} diff --git a/src/TSIGKeyAlgorithms.php b/src/TSIGKeyAlgorithms.php new file mode 100644 index 0000000..86da30f --- /dev/null +++ b/src/TSIGKeyAlgorithms.php @@ -0,0 +1,19 @@ + $this->data->getName(), + 'id' => $this->data->getId(), + 'algorithm' => $this->data->getAlgorithm(), + 'key' => $this->data->getKey(), + 'type' => $this->data->getType() + ]; + } +}