| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958 |
- <?php
- namespace MGModule\DNSManager2\mgLibs\custom\dns\submodules;
- use Exception;
- use \MGModule\DNSManager2\mgLibs\custom\dns;
- use MGModule\DNSManager2\mgLibs\custom\dns\dnssec\DnsSec;
- use MGModule\DNSManager2\mgLibs\custom\dns\submodules\PowerDNSv4\RRSet;
- use MGModule\DNSManager2\mgLibs\custom\dns\utils\Patterns;
- use \MGModule\DNSManager2\mgLibs\custom\dns\exceptions;
- use \MGModule\DNSManager2\mgLibs\custom\dns\interfaces;
- use \MGModule\DNSManager2\mgLibs\custom\dns\record\Record;
- use MGModule\DNSManager2\mgLibs\custom\helpers\IdnaHelper;
- class PowerDNSV4 extends dns\SubmoduleAbstract implements
- interfaces\SubmoduleTTLInterface, interfaces\SubmoduleImportInterface, interfaces\SubmoduleRDNSInterface, interfaces\SubmoduleDNSSecInterface
- {
- const ERR_WHILE_REMOVING = 'errRemovingRecord';
- const ERR_WHILE_CREATING = 'errCreatingRecord';
- public $configFields = [
- 'hostname' => [
- 'friendlyName' => 'Hostname/IP',
- 'validators' => [
- 'required' => 'required',
- ]
- ],
- 'port' => [
- 'friendlyName' => 'Default Port',
- 'value' => '8081'
- ],
- 'ssl' => [
- 'friendlyName' => 'SSL',
- 'type' => 'yesno',
- ],
- 'apikey' => [
- 'friendlyName' => 'API Key',
- 'validators' => [
- 'required' => 'required',
- ]
- ],
- 'domain_type' => [
- 'friendlyName' => 'Domain Type',
- 'type' => 'select',
- 'options' => ['MASTER' => 'MASTER', 'SLAVE' => 'SLAVE', 'NATIVE' => 'NATIVE'],
- ],
- 'notify_slaves' => [
- 'friendlyName' => 'Notify Slaves',
- 'type' => 'yesno',
- ],
- 'zone_account' => [
- 'friendlyName' => 'Zone Account',
- ],
- 'increment_soa_serial'=>[
- 'friendlyName' => 'Manually Increment SOA Serial',
- 'type' => 'yesno',
- ],
- 'default_ip' => [
- 'friendlyName' => 'Default IP',
- 'validators' => [
- 'required' => 'required',
- 'pattern' => Patterns::IP4_OR_IP6,
- ]
- ],
- ];
- public $availableTypes = ['MINFO', 'A', 'AAAA', 'NS', 'MX', 'CNAME', 'TXT', 'SRV', 'DNAME', 'SPF', 'PTR', 'ALIAS', 'AFSDB', 'HINFO', 'LOC', 'NAPTR', 'RP', 'CAA', 'SOA', 'DNSKEY', 'DS', 'RRSIG', 'URI', 'TLSA', 'SMIMEA', 'CERT', 'SSHFP', 'NSEC3PARAM', 'NSEC3', 'NSEC'];
- private $zoneID = false;
- private function get( $function, $params = [], $customRequest = null )
- {
- $headers[] = 'X-API-Key: ' . $this->config['apikey'];
- $port = $this->config['port'] ? : 8081;
- $url = $this->config['ssl'] ? 'https' : 'http';
- $url .= '://' . $this->config['hostname'] . ':' . $port . '/api/v1/' . $function;
- $this->log('REQUEST: ' . $url);
- $ch = curl_init();
- $chOptions = [
- CURLOPT_URL => trim($url),
- CURLOPT_RETURNTRANSFER => 1,
- CURLOPT_SSL_VERIFYPEER => 0,
- CURLOPT_SSL_VERIFYHOST => 0,
- CURLOPT_TIMEOUT => 30,
- CURLOPT_HTTPHEADER => $headers
- ];
- if ( $params )
- {
- $body = json_encode($params);
- $body = str_replace(
- [
- ':{',
- '},',
- '}}',
- '}],{'
- ],
- [
- ':[{',
- '}],',
- '}]}',
- '},{'
- ], $body);
- $chOptions[CURLOPT_POST] = 1;
- $chOptions[CURLOPT_POSTFIELDS] = $body;
- }
- if ( $customRequest )
- {
- $chOptions[CURLOPT_CUSTOMREQUEST] = $customRequest;
- }
- curl_setopt_array($ch, $chOptions);
- $out = curl_exec($ch);
- $this->log('RESPONSE: ' . $out);
- if ( strpos($out, '"error"') !== false)
- {
- $out = json_decode($out);
- throw new exceptions\DNSSubmoduleException(str_replace('\032', ' ', $out->error), dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- if ( strpos($out, 'Unauthorized') !== false )
- {
- throw new exceptions\DNSSubmoduleException('Incorrect API Key', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
- }
- if ( curl_errno($ch) )
- {
- throw new exceptions\DNSSubmoduleException('cURL Error: ' . curl_errno($ch) . ' - ' . curl_error($ch), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
- }
- $info = curl_getinfo($ch);
- if($info['http_code'] >= 300)
- {
- throw new exceptions\DNSSubmoduleException($this->parseHttpCodeError($info['http_code']), $info['http_code']);
- }
- curl_close($ch);
- return $out;
- }
- private function parseHttpCodeError($code)
- {
- switch($code)
- {
- case 400:
- $error = 'Bad request to the API';
- break;
- case 404:
- $error = 'API not enabled or invalid URL';
- break;
- default:
- $error = 'The server returned '.$code.' error';
- }
- return $error;
- }
- public function testConnection()
- {
- $out = $this->get('servers');
- }
- private function getServerID()
- {
- $out = json_decode($this->get('servers'));
- return $out[0]->id;
- }
- public function getZoneID()
- {
- if ( $this->zoneID !== false )
- {
- return $this->zoneID;
- }
- $serverId = $this->getServerID();
-
- try
- {
- $zone = json_decode($this->get("servers/$serverId/zones/" . $this->domain, []));
- }
- catch (exceptions\DNSSubmoduleException $e)
- {
- if($e->getCode() == 404)
- {
- throw new exceptions\DNSSubmoduleException('Zone does not exists', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- }
- if ( isset($zone->id) )
- {
- $this->zoneID = (string)$zone->id;
- return (string)$zone->id;
- }
- throw new exceptions\DNSSubmoduleException('Zone does not exists', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
- }
- public function zoneExists()
- {
- try
- {
- $this->getZoneID();
- return true;
- }
- catch (exceptions\DNSSubmoduleException $e)
- {
- if ( $e->getCode() === dns\SubmoduleExceptionCodes::INVALID_PARAMETERS )
- {
- return false;
- }
- throw $e;
- }
- }
- public function getRecords( $recordType = false )
- {
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $rrsets = json_decode($this->get("servers/$serverId/zones/$zoneId", []), false)->rrsets;
- $out = [];
- $rrsets = array_filter($rrsets, [self::class, 'filterBrokenRRSets']);
- /** @var dns\submodules\PowerDNSv4\RRSet $rrset */
- foreach ( $rrsets as $rrset )
- {
- $type = $rrset->type;
- $name = $rrset->name;
- $ttl = $rrset->ttl;
- $recordClass = 'MGModule\\DNSManager2\\mgLibs\\custom\\dns\\record\\type\\' . $type;
- $recordAdapterClass = 'MGModule\\DNSManager2\\mgLibs\\custom\\dns\\submodules\\PowerDNSv4\\Adapters\\' . $type . 'Adapter';
- if ( ($recordType && $recordType !== $type) || !class_exists($recordClass) || !in_array($type, $this->availableTypes, true) ) continue;
- /** @var dns\submodules\PowerDNSv4\RecordFromServer $recordFromServer */
- foreach ( $rrset->records as $recordId => $recordFromServer )
- {
- if ( class_exists($recordAdapterClass) && method_exists($recordAdapterClass, 'createRdata') )
- {
- /** @var dns\submodules\PowerDNSv4\Adapters\AbstractPowerDNSv4Adapter $record */
- $record = new $recordAdapterClass();
- $record->name = IdnaHelper::idnaEncode($name);
- $record->type = $type;
- $record->line = implode('|', [$name, $type, $recordId]);
- $record->ttl = $ttl;
- $record->class = 'IN';
- $record->createRdata(IdnaHelper::idnaDecode($recordFromServer->content));
- }
- else
- {
- $record = new Record();
- $record->name = IdnaHelper::idnaEncode($name);
- $record->type = $type;
- $record->line = implode('|', [$name, $type, $recordId]);
- $record->ttl = $ttl;
- $record->class = 'IN';
- $additionalProps = explode(' ', IdnaHelper::idnaDecode($recordFromServer->content));
- $record->rdata = new $recordClass();
- foreach ( array_keys(get_object_vars($record->rdata)) as $index => $additionalProperty )
- {
- $record->rdata->$additionalProperty = $additionalProps[$index];
- }
- }
- $out[] = $record;
- }
- }
- usort($out, static function ( $a, $b )
- {
- /** @var Record $a */
- /** @var Record $b */
- $recordAllignment = ['SOA', 'A', 'AAAA', 'NS', 'MX', 'TXT'];
- if ( !in_array($a->type, $recordAllignment, true) && !in_array($b->type, $recordAllignment, true) ) return 0;
- if ( !in_array($a->type, $recordAllignment, true) ) return 1;
- if ( !in_array($b->type, $recordAllignment, true) ) return -1;
- if ( $a->type === $b->type )
- {
- return $a->name < $b->name ? -1 : 1;
- }
- return array_search($a->type, $recordAllignment, true) < array_search($b->type, $recordAllignment, true) ? -1 : 1;
- });
- return $out;
- }
- /**
- * Generates Valid RRSet format for one record ( usefull when we can use replace function )
- *
- * @param Record $record
- * @param string $changetype
- *
- * @return array
- */
- private function recordToParamsArray( dns\record\Record $record, $changetype = 'REPLACE' )
- {
- return [
- 'rrsets' => [
- 'name' => $record->name,
- 'type' => $record->type,
- 'ttl' => $record->ttl,
- 'changetype' => $changetype,
- 'comments' => [],
- 'records' => [$this->formatRecordToPowerDnsFormat($record)]
- ]
- ];
- }
- /**
- * @param Record $record
- *
- * @throws exceptions\DNSSubmoduleException
- */
- public function addRecord( dns\record\Record $record )
- {
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $records = $this->getRecords();
- $record->name = IdnaHelper::idnaEncode($record->nameToAbsolute($this->domain));
- $records[] = $record;
- if( $this->config['increment_soa_serial'] === 'on' )
- {
- $records = $this->incrementSOASerial($records);
- }
- $params = $this->recordsToParamArray($records);
- $params = $this->replaceTargetRRSetTTL($params, $record);
- $this->get("servers/$serverId/zones/$zoneId", $params, 'PATCH');
- if ( $this->isSigned() )
- {
- $this->rectify();
- }
- $this->checkAndRunNotifySlaves($serverId, $zoneId);
- }
- public function editRecord( dns\record\Record $record )
- {
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $record->nameToAbsolute($this->domain);
- $record->name = IdnaHelper::idnaEncode($record->name);
- $records = $this->getRecords();
- $recordsBeforeUpdate = $records;
- /** @var Record $records */
- foreach ( $records as $index => $recordBeforeUpdate )
- {
- if ( $recordBeforeUpdate->line === $record->line )
- {
- $records[$index] = $record;
- break;
- }
- }
- if( $this->config['increment_soa_serial'] === 'on' )
- {
- $records = $this->incrementSOASerial($records);
- }
- $params = $this->recordsToParamArray($records);
- $params = $this->replaceTargetRRSetTTL($params, $record);
- $errorType = null;
- try
- {
- $this->removeRRsets($recordsBeforeUpdate);
- }
- catch( exceptions\DNSSubmoduleException $e )
- {
- $errorType = self::ERR_WHILE_REMOVING;
- }
- try
- {
- $this->get("servers/$serverId/zones/$zoneId", $params, 'PATCH');
- }
- catch( exceptions\DNSSubmoduleException $e )
- {
- $errorType = $errorType ? : self::ERR_WHILE_CREATING;
- $this->restoreOldRecords($recordsBeforeUpdate,$errorType);
- }
- if ( $this->isSigned() )
- {
- $this->rectify();
- }
- }
- public function deleteRecord( dns\record\Record $record )
- {
- if( $record->type === 'SOA' ) throw new exceptions\DNSSubmoduleException('You are not allowed to delete SOA record');
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $record->nameToAbsolute($this->domain);
- $record->name = IdnaHelper::idnaEncode($record->name);
- $records = $this->getRecords();
- $recordsBeforeUpdate = $records;
- /** @var Record $records */
- foreach ( $records as $index => $recordBeforeUpdate )
- {
- if ( $recordBeforeUpdate->line === $record->line )
- {
- unset($records[$index]);
- break;
- }
- }
- $params = $this->recordsToParamArray($records);
- $errorType = null;
- try
- {
- $this->removeRRsets($recordsBeforeUpdate);
- }
- catch( exceptions\DNSSubmoduleException $e )
- {
- $errorType = self::ERR_WHILE_REMOVING;
- }
- try
- {
- $this->get("servers/$serverId/zones/$zoneId", $params, 'PATCH');
- }
- catch( exceptions\DNSSubmoduleException $e )
- {
- $errorType = $errorType ? : self::ERR_WHILE_CREATING;
- $this->restoreOldRecords($recordsBeforeUpdate, $errorType);
- }
- if ( $this->isSigned() )
- {
- $this->rectify();
- }
- $this->checkAndRunNotifySlaves($serverId, $zoneId);
- }
- public function activateZone( $dnsZoneName = false )
- {
- $serverId = $this->getServerID();
- $params = [
- 'name' => rtrim($this->domain, '.') . '.',
- 'kind' => $this->config['domain_type'],
- 'nameservers' => [],
- ];
- if ( !empty($this->config['zone_account']) )
- {
- $params['account'] = $this->config['zone_account'];
- }
- if ( $dnsZoneName )
- {
- $params['name'] = rtrim($dnsZoneName, '.') . '.';
- }
- return $this->get("servers/$serverId/zones", $params);
- }
- public function terminateZone()
- {
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $this->get("servers/$serverId/zones/$zoneId", [], 'DELETE');
- }
- public function getZones()
- {
- $serverId = $this->getServerID();
- $ret = json_decode($this->get("servers/$serverId/zones", []));
- $out = [];
- foreach ( $ret as $zone )
- {
- $masters = null;
- if ( !empty($zone->masters) )
- {
- $masters = implode(', ', $zone->masters);
- }
- $out[substr((string)$zone->name, 0, -1)] = $masters;
- }
- return $out;
- }
- public function updateRDNS( $ip, $ttl = false, $value = false )
- {
- $revDnsZoneName = dns\utils\ReverseDNSHelper::reverseZoneName($ip);
- $zoneId = $this->getRevDNSZoneID($revDnsZoneName);
- $serverId = $this->getServerID();
- if ( !$zoneId )
- {
- $this->activateZone($revDnsZoneName);
- $zoneId = $this->getRevDNSZoneID($revDnsZoneName);
- }
- //We don't allow to replace name of the rdns record so we can simply use patch
- $revRecord = $this->createPowerDnsPTRRecord($ip, $ttl, $value, $revDnsZoneName);
- $this->get("servers/$serverId/zones/$zoneId", $this->recordToParamsArray($revRecord), 'PATCH');
- $this->checkAndRunNotifySlaves($serverId, $zoneId);
- }
- private function createPowerDnsPTRRecord( $ip, $ttl, $value, $dnsZoneName )
- {
- $record = new Record();
- $record->name = $this->getLastPartOfIp($ip, true) . rtrim($dnsZoneName, '.') . '.';
- $record->ttl = $ttl;
- $record->type = 'PTR';
- $record->rdata = new dns\record\type\PTR();
- $record->rdata->ptrdname = $value;
- return $record;
- }
- public function removeRDNS( $ip )
- {
- $revDnsZoneName = dns\utils\ReverseDNSHelper::reverseZoneName($ip);
- $zoneId = $this->getRevDNSZoneID($revDnsZoneName);
- if ( !$zoneId )
- {
- return false;
- }
- $record = $this->getRDNSRecord($ip);
- if ( $record === false )
- {
- return false;
- }
- $this->deleteRecord($record);
- return true;
- }
- private function getLastPartOfIp( $ip, $withDot = false )
- {
- $ipLastPart = dns\utils\ReverseDNSHelper::reverseRecordName($ip);
- return $withDot ? $ipLastPart . '.' : $ipLastPart;
- }
- public function getRDNSRecord( $ip )
- {
- $clonedZone = $this->getClone($ip);
- $records = $clonedZone->getRecords('PTR');
- $revZoneName = $this->getLastPartOfIp($ip, true) . rtrim(dns\utils\ReverseDNSHelper::reverseZoneName($ip), '.') . '.';
- foreach ( $records as $record )
- {
- if ( $record->name === $revZoneName ) return $record;
- }
- return false;
- }
- private function getRevDNSZoneID( $zoneName )
- {
- $zoneName = rtrim($zoneName, '.') . '.';
- $serverId = $this->getServerID();
- $out = json_decode($this->get("servers/$serverId/zones", []));
- foreach ( $out as $zone )
- {
- if ( $zone->name === $zoneName )
- {
- $this->zoneID = (string)$zone->id;
- return (string)$zone->id;
- }
- }
- return false;
- }
- private function checkAndRunNotifySlaves( $serverID = null, $zoneID = null )
- {
- if ( $serverID !== null && $zoneID !== null && $this->config['notify_slaves'] === 'on' )
- {
- $this->get('servers/' . $serverID . '/zones/' . $zoneID . '/notify', [], 'PUT');
- }
- }
- //DNS SEC
- public function getSignKeys()
- {
- $dnssec = new \MGModule\DNSManager2\mgLibs\custom\dns\dnssec\DnsSec();
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $ret = json_decode($this->get("servers/$serverId/zones/$zoneId/cryptokeys", []));
- foreach ( $ret as $record )
- {
- foreach ( $record->ds as $dsRecord )
- {
- $ex = explode(' ', $dsRecord);
- $ds = new dns\record\type\DS();
- $ds->setKeytag($ex[0]);
- $ds->setAlgorithm($ex[1]);
- $ds->setDigestType($ex[2]);
- $ds->setDigest($ex[3]);
- $dnssec->addDs($ds);
- }
- switch ( strtolower($record->keytype) )
- {
- case 'csk':
- $dnsKeyEx = explode(' ', $record->dnskey);
- $dnskey = new dns\record\type\DNSKEY();
- $dnskey->setFlags($dnsKeyEx[0]);
- $dnskey->setProtocol($dnsKeyEx[1]);
- $dnskey->setAlgorithm($dnsKeyEx[2]);
- $dnskey->setPublicKey($dnsKeyEx[3]);
- $zoneKey = new dns\dnssec\CSK();
- $zoneKey->setId($record->id);
- $zoneKey->setBits($record->bits);
- $zoneKey->setDnsKey($dnskey);
- $dnssec->addKey($zoneKey);
- break;
- case 'ksk':
- case 'zsk':
- $dnsKeyEx = explode(' ', $record->dnskey);
- $dnskey = new dns\record\type\DNSKEY();
- $dnskey->setFlags($dnsKeyEx[0]);
- $dnskey->setProtocol($dnsKeyEx[1]);
- $dnskey->setAlgorithm($dnsKeyEx[2]);
- $dnskey->setPublicKey($dnsKeyEx[3]);
- $dnskey2 = new dns\record\type\DNSKEY();
- $dnskey2->setFlags($dnsKeyEx[0]);
- $dnskey2->setProtocol($dnsKeyEx[1]);
- $dnskey2->setAlgorithm($dnsKeyEx[2]);
- $ksk = new dns\dnssec\KSK();
- $ksk->setId($record->id);
- $ksk->setBits($record->bits);
- $ksk->setDnsKey($dnskey);
- $zsk = new dns\dnssec\ZSK();
- $zsk->setId($record->id);
- $zsk->setBits($record->bits);
- $zsk->setDnsKey($dnskey2);
- $dnssec->addKey($ksk);
- $dnssec->addKey($zsk);
- break;
- }
- }
- return $dnssec;
- }
- /**
- * Sign DNS zone
- */
- public function sign()
- {
- $this->changeStatus(true);
- }
- /**
- * Unsign DNS zone
- */
- public function unsign()
- {
- $this->changeStatus(false);
- }
- private function changeStatus( $status = true, $dnsZoneName = null )
- {
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $params = [
- 'dnssec' => (boolean)$status,
- ];
- if ( $dnsZoneName )
- {
- $params['name'] = rtrim($dnsZoneName, '.') . '.';
- }
- $this->get("servers/$serverId/zones/$zoneId", $params, 'PUT');
- }
- /**
- * Rectify DNS zone
- */
- public function rectify()
- {
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $this->get("servers/$serverId/zones/$zoneId/rectify", [], 'PUT');
- }
- /**
- *
- */
- public function isSigned()
- {
- try
- {
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- return json_decode($this->get("servers/$serverId/zones/$zoneId", []))->dnssec;
- }
- catch ( Exception $ex)
- {
- return false;
- }
- }
- /**
- * Creates rrsets structure from Records array
- * @param array $records
- * @param string $changeType
- * @return mixed
- */
- private function recordsToParamArray( $records, $changeType = 'REPLACE')
- {
- $names = $this->getUniqueNames($records);
- $types = $this->getUniqueTypes($records);
- if( $changeType === 'DELETE' )
- {
- $types = array_diff($types, ['SOA']);
- }
- $out = ['rrsets' => []];
- foreach ( $names as $name )
- {
- foreach ( $types as $type )
- {
- $rrset = new RRSet();
- $rrset->name = $name;
- $rrset->type = $type;
- $rrset->ttl = $this->getRRSetTTL($name, $type, $records);
- $rrset->changetype = $changeType;
- $rrset->comments = [];
- $rrset->records = $this->getRRsetForNameAndType($name, $type, $records);
- if ( $rrset->records )
- {
- $out['rrsets'][] = $rrset;
- }
- }
- }
- return $out;
- }
- /**
- * @param array $records
- * @return array
- */
- private function getUniqueNames( $records )
- {
- $names = [];
- /** @var Record $record */
- foreach ( $records as $record )
- {
- $names[] = $record->name;
- }
- return array_unique($names);
- }
- /**
- * @param array $records
- * @return array
- */
- private function getUniqueTypes( $records )
- {
- $types = [];
- /** @var Record $record */
- foreach ( $records as $record )
- {
- $types[] = $record->type;
- }
- return array_unique($types);
- }
- /**
- * @param $name
- * @param $type
- * @param $records
- * @return array
- */
- private function getRRsetForNameAndType( $name, $type, $records )
- {
- $out = [];
- foreach ( $records as $record )
- {
- if ( $record->name === $name && $record->type === $type )
- {
- $out[] = $this->formatRecordToPowerDnsFormat($record);
- }
- }
- return $out;
- }
- /**
- * @param Record $record
- * @return array
- */
- private function formatRecordToPowerDnsFormat( Record $record )
- {
- $recordAdapterClass = 'MGModule\\DNSManager2\\mgLibs\\custom\\dns\\submodules\\PowerDNSv4\\Adapters\\' . $record->type . 'Adapter';
- if ( class_exists($recordAdapterClass) && method_exists($recordAdapterClass, 'parseContentToApiFormat') )
- {
- $content = (new $recordAdapterClass)->parseContentToApiFormat($record->rdata);
- }
- else
- {
- $content = str_replace("\t",' ',$record->rdata->toString());
- }
- return ['content' => $content, 'disabled' => false];
- }
- /**
- * Function removes all RRsets from server
- * It's easier when we remove all and then add all since we can't update single record cuz REPLACE duplicates record
- * @param $records
- * @return bool
- * @throws exceptions\DNSSubmoduleException
- */
- private function removeRRsets( $records )
- {
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $removeParams = $this->recordsToParamArray($records, 'DELETE');
- $this->get("servers/$serverId/zones/$zoneId", $removeParams, 'PATCH');
- if( count($this->getRecords()) )
- {
- throw new exceptions\DNSSubmoduleException(self::ERR_WHILE_REMOVING);
- }
- return true;
- }
- /**
- * @param string $name
- * @param string $type
- * @param array $records
- *
- * @return int
- */
- private function getRRSetTTL( $name, $type, array $records )
- {
- foreach( $records as $record )
- {
- if( $record->type === $type && $record->name === $name )
- {
- return $record->ttl;
- }
- }
- return 3600;
- }
- /**
- * @param array $params
- * @param Record $record
- *
- * @return mixed
- */
- private function replaceTargetRRSetTTL( $params, Record $record )
- {
- /*** @var RRSet $rrset */
- foreach( $params['rrsets'] as $index => $rrset )
- {
- if( $rrset->name === $record->name && $rrset->type === $record->type )
- {
- $params['rrsets'][$index]->ttl = $record->ttl ?: 3600;
- return $params;
- }
- }
- return $params;
- }
- /**
- * @param array $oldRecords
- * @param string $errorType
- *
- * @throws exceptions\DNSSubmoduleException
- */
- private function restoreOldRecords( $oldRecords, $errorType = self::ERR_WHILE_CREATING )
- {
- $serverId = $this->getServerID();
- $zoneId = $this->getZoneID();
- $errors = [];
- foreach( $oldRecords as $oldRecord )
- {
- try
- {
- $this->get("servers/$serverId/zones/$zoneId", $this->recordToParamsArray($oldRecord), 'PATCH');
- }
- catch( exceptions\DNSSubmoduleException $e )
- {
- $errors[] = $e->getMessage();
- }
- }
- if( count($errors) )
- {
- $msg = $errorType === self::ERR_WHILE_REMOVING ? 'Zone corrupted contact administrator. Affected records: ' : 'Couldn\'t create records: ';
- throw new exceptions\DNSSubmoduleException($msg . implode('<br />', $errors));
- }
- }
- /**
- * @param RRSet $rrset
- *
- * @return bool
- */
- private function filterBrokenRRSets( $rrset )
- {
- $domainToCheck = rtrim(IdnaHelper::idnaEncode($this->domain), ' .') . '.';
- return (bool)preg_match('/' . preg_quote($domainToCheck, '/') . '$/', $rrset->name);
- }
- /**
- * @param array $records
- *
- * @return array
- */
- public function incrementSOASerial( array $records )
- {
- /** @var Record $record */
- foreach( $records as &$record )
- {
- if( $record->type === 'SOA' )
- {
- $record->rdata->serial++;
- return $records;
- }
- }
- }
- }
|