-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #138 from exonet/tsi/132-meta
- Loading branch information
Showing
10 changed files
with
723 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
<?php | ||
|
||
require __DIR__.'/../vendor/autoload.php'; | ||
|
||
require __DIR__.'/CliLogger.php'; | ||
|
||
use Exonet\Powerdns\MetaType; | ||
use Exonet\Powerdns\Powerdns; | ||
use Exonet\Powerdns\RecordType; | ||
|
||
$domain = 'zone-meta-test.nl'; | ||
$nameServers = ['ns1.example.com.', 'ns2.example.eu.']; | ||
$dnsRecords = [ | ||
['name' => '@', 'type' => RecordType::A, 'content' => '127.0.0.1', 'ttl' => 60], | ||
['name' => 'www', 'type' => RecordType::A, 'content' => '127.0.0.1', 'ttl' => 60], | ||
['name' => '@', 'type' => RecordType::AAAA, 'content' => '2a00:1e28:3:1629::1', 'ttl' => 60], | ||
]; | ||
|
||
// Update the key to the real PowerDNS API Key. | ||
$powerdns = new Powerdns('127.0.0.1', 'very_secret_secret'); | ||
|
||
// Uncomment this line to see what happens when executing this example on the command line. | ||
// $powerdns->setLogger(new CliLogger()); | ||
|
||
// Delete the zone if it already exists so this example can be executed multiple times. | ||
try { | ||
$powerdns->deleteZone($domain); | ||
} catch (\Exonet\Powerdns\Exceptions\PowerdnsException $e) { | ||
} | ||
|
||
// Create a new zone with the defined records and name servers. | ||
$powerdns->createZone($domain, $nameServers)->create($dnsRecords); | ||
|
||
// Get the zone. | ||
$zone = $powerdns->zone($domain); | ||
|
||
echo 'EXISTING META RECORDS:'.PHP_EOL; | ||
echo str_repeat('-', 40).PHP_EOL; | ||
foreach ($zone->meta()->get() as $metaItem) { | ||
echo $metaItem->getKind().': '.implode('; ', $metaItem->getData()).PHP_EOL; | ||
} | ||
|
||
// Create a new meta record. | ||
$result = $zone->meta()->create('X-Example', 'test'); | ||
|
||
// Create a new meta record with multiple values. | ||
$data = ['example.com', 'example.org']; | ||
$zone->meta()->create(MetaType::FORWARD_DNSUPDATE, $data); | ||
|
||
echo PHP_EOL.'NEW META RECORDS:'.PHP_EOL; | ||
echo str_repeat('-', 40).PHP_EOL; | ||
$metaSet = $zone->meta()->get(); | ||
foreach ($metaSet as $metaItem) { | ||
echo $metaItem->getKind().': '.implode('; ', $metaItem->getData()).PHP_EOL; | ||
} | ||
|
||
// Get the first meta record. | ||
$record = $metaSet[1]; | ||
|
||
// Update the meta record. | ||
$record->setData(['test', 'test2'])->save(); | ||
|
||
// Delete the meta record. | ||
$record->delete(); | ||
|
||
// Delete a specific meta record. | ||
$zone->meta()->get(MetaType::SOA_EDIT)->delete(); | ||
|
||
echo PHP_EOL.'UPDATED RECORDS:'.PHP_EOL; | ||
echo str_repeat('-', 40).PHP_EOL; | ||
foreach ($zone->meta()->get() as $metaItem) { | ||
echo $metaItem->getKind().': '.implode('; ', $metaItem->getData()).PHP_EOL; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
namespace Exonet\Powerdns\Exceptions; | ||
|
||
class InvalidMetaKind extends PowerdnsException | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?php | ||
|
||
namespace Exonet\Powerdns\Exceptions; | ||
|
||
class ReadOnlyException extends PowerdnsException | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
<?php | ||
|
||
namespace Exonet\Powerdns; | ||
|
||
use Exonet\Powerdns\Exceptions\InvalidMetaKind; | ||
use Exonet\Powerdns\Exceptions\ReadOnlyException; | ||
use Exonet\Powerdns\Resources\Meta as MetaResource; | ||
use Exonet\Powerdns\Resources\MetaSet; | ||
use Exonet\Powerdns\Transformers\MetaTransformer; | ||
|
||
class Meta extends AbstractZone | ||
{ | ||
/** | ||
* Get all the meta data for this zone, or only the meta data for a specific kind. | ||
* | ||
* @param string|null $metaKind If specified, only the meta data for this kind will be returned. | ||
* | ||
* @throws InvalidMetaKind When the meta kind is invalid. | ||
* | ||
* @return MetaSet The meta data set. | ||
*/ | ||
public function get(string $metaKind = null): MetaSet | ||
{ | ||
$items = $this->connector->get($this->getZonePath('/metadata/'.$metaKind)); | ||
|
||
// Wrap the result in an array if it's a single item. | ||
if (isset($items['kind'])) { | ||
$items = [$items]; | ||
} | ||
|
||
$resultSet = new MetaSet(); | ||
foreach ($items as $item) { | ||
$resultSet->addResource(new MetaResource($item['kind'], $item['metadata'] ?? [], $this)); | ||
} | ||
|
||
return $resultSet; | ||
} | ||
|
||
/** | ||
* Create a new meta data item. | ||
* | ||
* @param string $kind The meta kind. | ||
* @param array|string $data The meta data. | ||
* | ||
* @throws InvalidMetaKind When the meta kind is invalid. | ||
* @throws ReadOnlyException When the meta kind is read-only. | ||
* | ||
* @return MetaSet The created meta data set. | ||
*/ | ||
public function create(string $kind, $data): MetaSet | ||
{ | ||
$this->checkReadOnly($kind); | ||
$response = $this->connector->post($this->getZonePath('/metadata'), new MetaTransformer(new MetaResource($kind, $data))); | ||
|
||
return new MetaSet([new MetaResource($response['kind'], $response['metadata'] ?? [], $this)]); | ||
} | ||
|
||
/** | ||
* Update an existing meta data item. | ||
* | ||
* @param MetaResource $meta The meta data item to update. | ||
* | ||
* @throws ReadOnlyException When the meta kind is read-only. | ||
* | ||
* @return bool True if the update was successful. | ||
*/ | ||
public function update(MetaResource $meta): bool | ||
{ | ||
$this->checkReadOnly($meta->getKind()); | ||
$response = $this->connector->put($this->getZonePath('/metadata/'.$meta->getKind()), new MetaTransformer($meta)); | ||
|
||
// If the response is empty, everything is fine. | ||
return empty($response); | ||
} | ||
|
||
/** | ||
* Delete an existing meta data item. | ||
* | ||
* @param MetaResource $meta The meta data item to delete. | ||
* | ||
* @throws ReadOnlyException When the meta kind is read-only. | ||
* | ||
* @return bool True if the delete was successful. | ||
*/ | ||
public function delete(MetaResource $meta): bool | ||
{ | ||
$this->checkReadOnly($meta->getKind()); | ||
$response = $this->connector->delete($this->getZonePath('/metadata/'.$meta->getKind())); | ||
|
||
// If the response is empty, everything is fine. | ||
return empty($response); | ||
} | ||
|
||
/** | ||
* Check if the meta kind is read-only. | ||
* | ||
* @param string $kind The meta kind. | ||
* | ||
* @throws ReadOnlyException When the meta kind is read-only. | ||
*/ | ||
protected function checkReadOnly(string $kind): void | ||
{ | ||
if (in_array($kind, MetaType::READ_ONLY)) { | ||
throw new ReadOnlyException(sprintf('The meta kind [%s] is read-only.', $kind)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
<?php | ||
|
||
namespace Exonet\Powerdns; | ||
|
||
/** | ||
* List of possible DNS meta types supported by PowerDNS. | ||
* Source: https://doc.powerdns.com/authoritative/domainmetadata.html. | ||
*/ | ||
class MetaType | ||
{ | ||
/** | ||
* The following options can only be read (not written to) via the HTTP API metadata endpoint. | ||
*/ | ||
public const READ_ONLY = [ | ||
self::API_RECTIFY, | ||
self::AXFR_MASTER_TSIG, | ||
self::LUA_AXFR_SCRIPT, | ||
self::NSEC3NARROW, | ||
self::NSEC3PARAM, | ||
self::PRESIGNED, | ||
self::TSIG_ALLOW_AXFR, | ||
self::SOA_EDIT_API, | ||
]; | ||
|
||
/** | ||
* Per-zone AXFR ACLs can be stored in the domainmetadata table. | ||
*/ | ||
public const ALLOW_AXFR_FROM = 'ALLOW-AXFR-FROM'; | ||
|
||
/** | ||
* This metadata item controls whether a zone is fully rectified on changes to the contents of a zone made through | ||
* the API. | ||
* | ||
* @since PowerDNS 4.1.0 | ||
*/ | ||
public const API_RECTIFY = 'API-RECTIFY'; | ||
|
||
/** | ||
* The IP address to use as a source address for sending AXFR and IXFR requests. | ||
*/ | ||
public const AXFR_SOURCE = 'AXFR-SOURCE'; | ||
|
||
/** | ||
* A list of IP ranges that are allowed to perform updates on any domain. | ||
*/ | ||
public const ALLOW_DNSUPDATE_FROM = 'ALLOW-DNSUPDATE-FROM'; | ||
|
||
/** | ||
* This setting allows you to set the TSIG key required to do an DNS update. If you have GSS-TSIG enabled, you can | ||
* use Kerberos principals here. | ||
*/ | ||
public const TSIG_ALLOW_DNSUPDATE = 'TSIG-ALLOW-DNSUPDATE'; | ||
|
||
/** | ||
* Tell PowerDNS to forward to the master server if the zone is configured as slave. Masters are determined by the | ||
* masters field in the domains table. | ||
*/ | ||
public const FORWARD_DNSUPDATE = 'FORWARD-DNSUPDATE'; | ||
|
||
/** | ||
* This configures how the soa serial should be updated. | ||
*/ | ||
public const SOA_EDIT_DNSUPDATE = 'SOA-EDIT-DNSUPDATE'; | ||
|
||
/** | ||
* Send a notification to all slave servers after every update. | ||
*/ | ||
public const NOTIFY_DNSUPDATE = 'NOTIFY-DNSUPDATE'; | ||
|
||
/** | ||
* When notifying this domain, also notify this nameserver (can occur multiple times). | ||
*/ | ||
public const ALSO_NOTIFY = 'ALSO-NOTIFY'; | ||
|
||
/** | ||
* Use this named TSIG key to retrieve this zone from its master. | ||
*/ | ||
public const AXFR_MASTER_TSIG = 'AXFR-MASTER-TSIG'; | ||
|
||
/** | ||
* Allow this GSS principal to perform AXFR retrieval. | ||
* | ||
* @removed PowerDNS 4.3.1 | ||
* | ||
* @since PowerDNS 4.7.0 | ||
*/ | ||
public const GSS_ALLOW_AXFR_PRINCIPAL = 'GSS-ALLOW-AXFR-PRINCIPAL'; | ||
|
||
/** | ||
* Use this principal for accepting GSS context. | ||
*/ | ||
public const GSS_ACCEPTOR_PRINCIPAL = 'GSS-ACCEPTOR-PRINCIPAL'; | ||
|
||
/** | ||
* If set to 1, attempt IXFR when retrieving zone updates. Otherwise IXFR is not attempted. | ||
*/ | ||
public const IXFR = 'IXFR'; | ||
|
||
/** | ||
* Script to be used to edit incoming AXFRs. This value will override the lua-axfr-script setting. Use 'NONE' to | ||
* remove a global script. | ||
*/ | ||
public const LUA_AXFR_SCRIPT = 'LUA-AXFR-SCRIPT'; | ||
|
||
/** | ||
* Set to "1" to tell PowerDNS this zone operates in NSEC3 'narrow' mode. | ||
*/ | ||
public const NSEC3NARROW = 'NSEC3NARROW'; | ||
|
||
/** | ||
* NSEC3 parameters of a DNSSEC zone. Will be used to synthesize the NSEC3PARAM record. If present, NSEC3 is used, | ||
* if not present, zones default to NSEC. | ||
*/ | ||
public const NSEC3PARAM = 'NSEC3PARAM'; | ||
|
||
/** | ||
* This zone carries DNSSEC RRSIGs (signatures), and is presigned. PowerDNS sets this flag automatically upon | ||
* incoming zone transfers (AXFR) if it detects DNSSEC records in the zone. However, if you import a presigned zone | ||
* using zone2sql or pdnsutil load-zone you must explicitly set the zone to be PRESIGNED. Note that PowerDNS will | ||
* not be able to correctly serve the zone if the imported data is bogus or incomplete. | ||
* | ||
* If a zone is presigned, the content of the metadata must be "1" (without the quotes). Any other value will not | ||
* signal presignedness. | ||
*/ | ||
public const PRESIGNED = 'PRESIGNED'; | ||
|
||
/** | ||
* Whether to publish CDNSKEY and/or CDS records as defined in RFC 7344. | ||
* To publish CDNSKEY records of the KSKs for the zone, set PUBLISH-CDNSKEY to 1. | ||
* To publish CDS records for the KSKs in the zone, set PUBLISH-CDS to a comma- separated list of signature | ||
* algorithm numbers. | ||
*/ | ||
public const PUBLISH_CDNSKEY = 'PUBLISH-CDNSKEY'; | ||
public const PUBLISH_CDS = 'PUBLISH-CDS'; | ||
|
||
/** | ||
* If set to 1, will make PowerDNS renotify the slaves after an AXFR is received from a master. Any other value | ||
* means that no renotifies are done. If not set at all, action will depend on the slave-renotify setting. | ||
* | ||
* @since PowerDNS 4.3.0 | ||
*/ | ||
public const SLAVE_RENOTIFY = 'SLAVE-RENOTIFY'; | ||
|
||
/** | ||
* When serving this zone, modify the SOA serial number in one of several ways. Mostly useful to get slaves to | ||
* re-transfer a zone regularly to get fresh RRSIGs. | ||
*/ | ||
public const SOA_EDIT = 'SOA-EDIT'; | ||
|
||
/** | ||
* On changes to the contents of a zone made through the API, the SOA record will be edited according to the | ||
* SOA-EDIT-API rules. These rules are the same as the SOA-EDIT-DNSUPDATE rules. If not set during zone creation, | ||
* a SOA-EDIT-API metadata record is created and set to DEFAULT. If this record is removed from the backend, | ||
* the default behavior is to not do any SOA editing based on this setting. This is different from setting DEFAULT. | ||
*/ | ||
public const SOA_EDIT_API = 'SOA-EDIT-API'; | ||
|
||
/** | ||
* Allow these named TSIG keys to AXFR this zone. | ||
*/ | ||
public const TSIG_ALLOW_AXFR = 'TSIG-ALLOW-AXFR'; | ||
} |
Oops, something went wrong.