|
|
@@ -1,564 +1,700 @@
|
|
|
-<?php
|
|
|
-
|
|
|
-namespace MGModule\DNSManager2\mgLibs\custom\dns\submodules;
|
|
|
-
|
|
|
-use MGModule\DNSManager2\mgLibs\custom\dns;
|
|
|
-use MGModule\DNSManager2\mgLibs\custom\dns\exceptions\DNSSubmoduleException;
|
|
|
-use MGModule\DNSManager2\mgLibs\custom\dns\interfaces;
|
|
|
-use MGModule\DNSManager2\mgLibs\custom\dns\submodules\AWSRoute53 as AwsRouteHelpers;
|
|
|
-use MGModule\DNSManager2\mgLibs\custom\dns\submodules\AWSRoute53\AWSRoute53API;
|
|
|
-use MGModule\DNSManager2\mgLibs\custom\dns\submodules\AWSRoute53\AWSRoute53ResponseInterface;
|
|
|
-
|
|
|
-class AWSRoute53 extends dns\SubmoduleAbstract implements
|
|
|
- interfaces\SubmoduleRDNSInterface,
|
|
|
- interfaces\SubmoduleTTLInterface,
|
|
|
- interfaces\SubmoduleImportInterface,
|
|
|
- interfaces\SubmoduleRemoveDefaultRecords,
|
|
|
- interfaces\SubmoduleCustomParseEditZoneInput
|
|
|
-{
|
|
|
- public $configFields = [
|
|
|
- 'accessKeyId' => [
|
|
|
- 'friendlyName' => 'Access Key Id',
|
|
|
- 'validators' => [
|
|
|
- 'required' => 'required'
|
|
|
- ]
|
|
|
- ],
|
|
|
- 'secretAccessKey' => [
|
|
|
- 'friendlyName' => 'Secret Access Key',
|
|
|
- 'type' => 'password',
|
|
|
- 'validators' => [
|
|
|
- 'required' => 'required'
|
|
|
- ]
|
|
|
- ],
|
|
|
- 'region' => [
|
|
|
- 'friendlyName' => 'Region'
|
|
|
- ],
|
|
|
- 'delegation_set' => [
|
|
|
- 'friendlyName' => 'Delegation Set Id',
|
|
|
- 'validators' => [
|
|
|
- ]
|
|
|
- ],
|
|
|
- 'soa_edit' => [
|
|
|
- 'friendlyName' => 'Allow To Edit SOA Records',
|
|
|
- 'type' => 'yesno'
|
|
|
- ],
|
|
|
- 'delete_aws_ns' => [
|
|
|
- 'friendlyName' => 'Delete AWS NS Records After Zone Creation',
|
|
|
- 'type' => 'yesno'
|
|
|
- ],
|
|
|
- 'use_white_label_nameservers' => [
|
|
|
- 'friendlyName' => 'Using White Label Nameservers',
|
|
|
- 'type' => 'yesno',
|
|
|
- 'help' => 'Check this box if you are using White Label Nameservers'
|
|
|
- ],
|
|
|
- ];
|
|
|
-
|
|
|
- public $availableTypes = ['A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SOA', 'SPF', 'SRV', 'TXT'];
|
|
|
- /** @var AWSRoute53API */
|
|
|
- private $connection;
|
|
|
-
|
|
|
- public function testConnection()
|
|
|
- {
|
|
|
- if(!extension_loaded('SimpleXML'))
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException('This server requires SimpleXML PHP extension', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
|
|
|
- }
|
|
|
-
|
|
|
- $this->loadConnectionInstance();
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- $zones = $this->connection->testConnection();
|
|
|
- if($zones->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public function getNameServers( $index = false )
|
|
|
- {
|
|
|
- if($this->config['use_white_label_nameservers'] === 'on')
|
|
|
- {
|
|
|
- return (array)parent::getNameServers();
|
|
|
- }
|
|
|
- $this->loadConnectionInstance();
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- $zones = $this->connection->listZonesByName($this->domain);
|
|
|
- if( $zones->getResponseType() === 'error' )
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
- $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
- if( !$zone )
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException('Zone name is not valid!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
- $hostedZone = json_decode(json_encode($this->connection->getHostedZoneById($zone)->getParsedResponseBody()), true);
|
|
|
- return (array)$hostedZone['DelegationSet']['NameServers']['NameServer'];
|
|
|
- }
|
|
|
-
|
|
|
- public function getRecords($recordType = false)
|
|
|
- {
|
|
|
- $this->loadConnectionInstance();
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- $zones = $this->connection->listZonesByName($this->domain);
|
|
|
- if($zones->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
- if(!$zone)
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException('Zone name is not valid!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $records */
|
|
|
- $records = $this->connection->listRecords($zone);
|
|
|
- if($records->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($records->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $availableTypes = $recordType ? [$recordType] : $this->availableTypes;
|
|
|
-
|
|
|
- return AwsRouteHelpers\AWSRoute53ResponseParseHelper::prepareRecordList($records->getParsedResponseBody(), $availableTypes, $this->config['soa_edit'] === 'on');
|
|
|
- }
|
|
|
-
|
|
|
- public function addRecord(dns\record\Record $record)
|
|
|
- {
|
|
|
- $this->loadConnectionInstance();
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- $zones = $this->connection->listZonesByName($this->domain);
|
|
|
- if($zones->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
- if(!$zone)
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException('Zone name is not valid!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $aliasType = $this->gatAliasTypeIfRequired($record);
|
|
|
- if(!$aliasType)
|
|
|
- {
|
|
|
- $rSet = $this->matchSetForRecord($record);
|
|
|
- }
|
|
|
-
|
|
|
- if(isset($rSet) && $rSet)
|
|
|
- {
|
|
|
- AwsRouteHelpers\AWSRoute53ResponseParseHelper::mergeHostsRecordsForRdata($rSet, $record, $rSet->type);
|
|
|
-
|
|
|
- return $this->editRecord($rSet);
|
|
|
- }
|
|
|
- $record->name = $record->nameToAbsolute($this->domain);
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $aRecord */
|
|
|
- $aRecord = $this->connection->createRecord($zone, $record, $aliasType);
|
|
|
- if($aRecord->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($aRecord->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public function editRecord(dns\record\Record $record)
|
|
|
- {
|
|
|
- $this->loadConnectionInstance();
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- $zones = $this->connection->listZonesByName($this->domain);
|
|
|
- if($zones->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
- if(!$zone)
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException('Zone name is not valid!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $aliasType = $this->gatAliasTypeIfRequired($record);
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $aRecord */
|
|
|
- $aRecord = $this->connection->updateRecord($zone, $record, $aliasType);
|
|
|
- if($aRecord->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($aRecord->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public function deleteRecord(dns\record\Record $record)
|
|
|
- {
|
|
|
- $this->loadConnectionInstance();
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- $zones = $this->connection->listZonesByName($this->domain);
|
|
|
- if($zones->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
- if(!$zone)
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException('Zone name is not valid!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $aliasType = $this->gatAliasTypeIfRequired($record);
|
|
|
- if(!$aliasType)
|
|
|
- {
|
|
|
- $rSet = $this->matchSetForRecord($record);
|
|
|
- }
|
|
|
-
|
|
|
- if(isset($rSet) && $rSet)
|
|
|
- {
|
|
|
- return $this->editRecord($rSet);
|
|
|
- }
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $aRecord */
|
|
|
- $aRecord = $this->connection->deleteRecord($zone, $record, $aliasType);
|
|
|
- if($aRecord->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($aRecord->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public function zoneExists()
|
|
|
- {
|
|
|
- $this->loadConnectionInstance();
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- $zones = $this->connection->listZonesByName($this->domain);
|
|
|
- if($zones->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
-
|
|
|
- return $zone ? true : false;
|
|
|
- }
|
|
|
-
|
|
|
- public function activateZone()
|
|
|
- {
|
|
|
- $this->loadConnectionInstance();
|
|
|
- $this->log('ACTIVATE ZONE');
|
|
|
- if($this->zoneExists())
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException('Domain name already exists!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- if(empty($this->domain))
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException('Domain name is not valid!', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
|
|
|
- }
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zone */
|
|
|
- $zone = $this->connection->createZone($this->domain, $this->config['delegation_set']);
|
|
|
- if($zone->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zone->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public function terminateZone()
|
|
|
- {
|
|
|
- $records = $this->getRecords();
|
|
|
- foreach($records as $record)
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- $this->deleteRecord($record);
|
|
|
- }
|
|
|
- catch(DNSSubmoduleException $exc)
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- $zones = $this->connection->listZonesByName($this->domain);
|
|
|
- if($zones->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $zonesId = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
- if($zonesId === false)
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException('Zone name is not valid!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $deleted */
|
|
|
- $deleted = $this->connection->deleteHostedZone($zonesId);
|
|
|
- if($deleted->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($deleted->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public function getZones()
|
|
|
- {
|
|
|
- $this->loadConnectionInstance();
|
|
|
- $zones = $this->connection->listZones();
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- if($zones->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return AwsRouteHelpers\AWSRoute53ResponseParseHelper::zoneListXmlToArray($zones->getParsedResponseBody());
|
|
|
- }
|
|
|
-
|
|
|
- private function loadConnectionInstance()
|
|
|
- {
|
|
|
- if(!$this->connection)
|
|
|
- {
|
|
|
- $responseHandler = new AwsRouteHelpers\AWSRoute53Response();
|
|
|
- $requestHandler = new AwsRouteHelpers\AWSRoute53Request(
|
|
|
- $responseHandler,
|
|
|
- $this->config['accessKeyId'],
|
|
|
- $this->config['secretAccessKey'],
|
|
|
- $this->config['region']
|
|
|
- );
|
|
|
-
|
|
|
- $apiHandler = new AwsRouteHelpers\AWSRoute53API($requestHandler);
|
|
|
-
|
|
|
- $this->connection = $apiHandler;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function updateRDNS($ip, $ttl = false, $value = false)
|
|
|
- {
|
|
|
- $revDnsZoneName = dns\utils\ReverseDNSHelper::reverseZoneName($ip);
|
|
|
- $zoneId = $this->getRevDNSZoneID($revDnsZoneName);
|
|
|
-
|
|
|
- if(!$zoneId)
|
|
|
- {
|
|
|
- $zoneId = $this->createRevDnsZone($revDnsZoneName);
|
|
|
- }
|
|
|
-
|
|
|
- $revRecord = dns\utils\ReverseDNSHelper::createPTRRecord($ip, $ttl, $value);
|
|
|
- $revRecord->name .= '.'.$revDnsZoneName;
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $aRecord */
|
|
|
- $aRecord = $this->connection->updateRecord($zoneId, $revRecord);
|
|
|
- if($aRecord->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($aRecord->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public function removeRDNS($ip)
|
|
|
- {
|
|
|
- $revDnsZoneName = dns\utils\ReverseDNSHelper::reverseZoneName($ip);
|
|
|
- $zoneId = $this->getRevDNSZoneID($revDnsZoneName);
|
|
|
- if(!$zoneId)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $records */
|
|
|
- $records = $this->connection->listRecords($zoneId);
|
|
|
- if($records->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($records->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
- $recordPrev = dns\utils\ReverseDNSHelper::reverseRecordName($ip);
|
|
|
- $recordName = $recordPrev.'.'.$revDnsZoneName;
|
|
|
-
|
|
|
- $recordToRemove = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findPtrRecordByName($records->getParsedResponseBody(), $recordName);
|
|
|
-
|
|
|
- if(!$recordToRemove)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $aRecord */
|
|
|
- $aRecord = $this->connection->deleteRecord($zoneId, $recordToRemove);
|
|
|
- if($aRecord->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($aRecord->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- public function getRDNSRecord($ip)
|
|
|
- {
|
|
|
- $revDnsZoneName = dns\utils\ReverseDNSHelper::reverseZoneName($ip);
|
|
|
- $zoneId = $this->getRevDNSZoneID($revDnsZoneName);
|
|
|
-
|
|
|
- if(!$zoneId)
|
|
|
- {
|
|
|
- return [];
|
|
|
- }
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $records */
|
|
|
- $records = $this->connection->listRecords($zoneId);
|
|
|
- if($records->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($records->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return AwsRouteHelpers\AWSRoute53ResponseParseHelper::prepareRecordList($records->getParsedResponseBody(), $this->availableTypes, $this->config['soa_edit'] === 'on');
|
|
|
- }
|
|
|
-
|
|
|
- private function getRevDNSZoneID($zoneName)
|
|
|
- {
|
|
|
- $this->loadConnectionInstance();
|
|
|
-
|
|
|
- /** @var AWSRoute53ResponseInterface $zones */
|
|
|
- $zones = $this->connection->listZonesByName($zoneName);
|
|
|
- if($zones->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $zoneName);
|
|
|
-
|
|
|
- return $zone ? : false;
|
|
|
- }
|
|
|
-
|
|
|
- private function createRevDnsZone($revDnsZoneName)
|
|
|
- {
|
|
|
- /** @var AWSRoute53ResponseInterface $zone */
|
|
|
- $zone = $this->connection->createZone($revDnsZoneName);
|
|
|
- if($zone->getResponseType() === 'error')
|
|
|
- {
|
|
|
- throw new DNSSubmoduleException($zone->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
- }
|
|
|
-
|
|
|
- return AwsRouteHelpers\AWSRoute53ResponseParseHelper::getZoneIdFromCreateConfirmation($zone->getParsedResponseBody());
|
|
|
- }
|
|
|
-
|
|
|
- private function gatAliasTypeIfRequired($record)
|
|
|
- {
|
|
|
- if($record->type !== 'ALIAS')
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- $dNamePos = stripos($record->name, trim($this->domain, '.'));
|
|
|
- if(!$dNamePos && $dNamePos !== 0)
|
|
|
- {
|
|
|
- $record->name .= '.'.$this->domain;
|
|
|
- }
|
|
|
-
|
|
|
- $deafultType = 'A';
|
|
|
-
|
|
|
- $recordsList = $this->getRecords();
|
|
|
- foreach($recordsList as $rec)
|
|
|
- {
|
|
|
- $trimedName = trim($rec->name, '.');
|
|
|
- if(($rec->name === $record->rdata->target || $trimedName === $record->rdata->target ) && $rec->type === 'AAAA')
|
|
|
- {
|
|
|
- return 'AAAA';
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return $deafultType;
|
|
|
- }
|
|
|
-
|
|
|
- public function convertInputFormData(&$input)
|
|
|
- {
|
|
|
- AwsRouteHelpers\AWSRoute53ResponseParseHelper::convertInputFormData($input);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * @param dns\record\Record $record
|
|
|
- * @return bool|dns\record\Record
|
|
|
- * @throws DNSSubmoduleException
|
|
|
- */
|
|
|
- public function matchSetForRecord( dns\record\Record $record)
|
|
|
- {
|
|
|
- $cRecord = clone $record;
|
|
|
- $allowedTypes = ['MX', 'A', 'AAAA', 'NS'];
|
|
|
- if(!in_array($cRecord->type, $allowedTypes, true) )
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- $basicRdata = $cRecord->rdata->toString();
|
|
|
- $cRecord->createRDATAObject($cRecord->type);
|
|
|
- $cRecord->rdata = null;
|
|
|
- $recordList = $this->getRecords();
|
|
|
- foreach($recordList as $rec)
|
|
|
- {
|
|
|
- if($cRecord->type === $rec->type && trim($cRecord->name, '.') === trim($rec->name, '.'))
|
|
|
- {
|
|
|
- if($rec->rdata->toString() === $basicRdata)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- AwsRouteHelpers\AWSRoute53ResponseParseHelper::mergeHostsRecordsForRdata($cRecord, $rec, $cRecord->type);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return $cRecord->rdata !== null ? $cRecord : false;
|
|
|
- }
|
|
|
-
|
|
|
- public function removeDefaultServerRecords($defaultModuleRecords)
|
|
|
- {
|
|
|
- if($this->config['delete_aws_ns'] !== 'on')
|
|
|
- {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- $cRecords = $this->getRecords();
|
|
|
- foreach($cRecords as $cRecord)
|
|
|
- {
|
|
|
- if($cRecord->type !== 'NS')
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- $found = false;
|
|
|
- foreach($defaultModuleRecords as $dRecord)
|
|
|
- {
|
|
|
- if($this->areRecordsEqual($cRecord, $dRecord))
|
|
|
- {
|
|
|
- $found = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if($found === false)
|
|
|
- {
|
|
|
- $this->deleteRecord($cRecord);
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- private function areRecordsEqual( dns\record\Record $rec1, dns\record\Record $rec2)
|
|
|
- {
|
|
|
- $recAname = rtrim($rec1->name,'.');
|
|
|
- $recBname = rtrim($rec2->name,'.');
|
|
|
-
|
|
|
- return $recAname === $recBname &&
|
|
|
- $rec1->type === $rec2->type &&
|
|
|
- $rec1->ttl === $rec2->ttl &&
|
|
|
- $rec1->rdata->toString() === $rec2->rdata->toString();
|
|
|
- }
|
|
|
-}
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace MGModule\DNSManager2\mgLibs\custom\dns\submodules;
|
|
|
+
|
|
|
+use MGModule\DNSManager2\mgLibs\custom\dns;
|
|
|
+use MGModule\DNSManager2\mgLibs\custom\dns\exceptions\DNSSubmoduleException;
|
|
|
+use MGModule\DNSManager2\mgLibs\custom\dns\interfaces;
|
|
|
+use MGModule\DNSManager2\mgLibs\custom\dns\submodules\AWSRoute53 as AwsRouteHelpers;
|
|
|
+use MGModule\DNSManager2\mgLibs\custom\dns\submodules\AWSRoute53\AWSRoute53API;
|
|
|
+use MGModule\DNSManager2\mgLibs\custom\dns\submodules\AWSRoute53\AWSRoute53ResponseInterface;
|
|
|
+use MGModule\DNSManager2\mgLibs\custom\dns\submodules\AWSRoute53\AWSRoute53ResponseParseHelper;
|
|
|
+use MGModule\DNSManager2\mgLibs\custom\helpers\IdnaHelper;
|
|
|
+
|
|
|
+class AWSRoute53 extends dns\SubmoduleAbstract implements
|
|
|
+ interfaces\SubmoduleRDNSInterface,
|
|
|
+ interfaces\SubmoduleTTLInterface,
|
|
|
+ interfaces\SubmoduleImportInterface,
|
|
|
+ interfaces\SubmoduleRemoveDefaultRecords,
|
|
|
+ interfaces\SubmoduleCustomParseEditZoneInput
|
|
|
+{
|
|
|
+ public $configFields = [
|
|
|
+ 'accessKeyId' => [
|
|
|
+ 'friendlyName' => 'Access Key Id',
|
|
|
+ 'validators' => [
|
|
|
+ 'required' => 'required'
|
|
|
+ ]
|
|
|
+ ],
|
|
|
+ 'secretAccessKey' => [
|
|
|
+ 'friendlyName' => 'Secret Access Key',
|
|
|
+ 'type' => 'password',
|
|
|
+ 'validators' => [
|
|
|
+ 'required' => 'required'
|
|
|
+ ]
|
|
|
+ ],
|
|
|
+ 'region' => [
|
|
|
+ 'friendlyName' => 'Region'
|
|
|
+ ],
|
|
|
+ 'delegation_set' => [
|
|
|
+ 'friendlyName' => 'Delegation Set Id',
|
|
|
+ 'validators' => [
|
|
|
+ ]
|
|
|
+ ],
|
|
|
+ 'soa_edit' => [
|
|
|
+ 'friendlyName' => 'Allow To Edit SOA Records',
|
|
|
+ 'type' => 'yesno'
|
|
|
+ ],
|
|
|
+ 'delete_aws_ns' => [
|
|
|
+ 'friendlyName' => 'Delete AWS NS Records After Zone Creation',
|
|
|
+ 'type' => 'yesno'
|
|
|
+ ],
|
|
|
+ 'use_white_label_nameservers' => [
|
|
|
+ 'friendlyName' => 'Using White Label Nameservers',
|
|
|
+ 'type' => 'yesno',
|
|
|
+ 'help' => 'Check this box if you are using White Label Nameservers'
|
|
|
+ ],
|
|
|
+ ];
|
|
|
+
|
|
|
+ public $availableTypes = ['A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR', 'SOA', 'SPF', 'SRV', 'TXT'];
|
|
|
+ /** @var AWSRoute53API */
|
|
|
+ private $connection;
|
|
|
+
|
|
|
+ public function testConnection()
|
|
|
+ {
|
|
|
+ if(!extension_loaded('SimpleXML'))
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException('This server requires SimpleXML PHP extension', dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $zones */
|
|
|
+ $zones = $this->connection->testConnection();
|
|
|
+ if($zones->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::CONNECTION_PROBLEM);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getNameServers( $index = false )
|
|
|
+ {
|
|
|
+ if($this->config['use_white_label_nameservers'] === 'on')
|
|
|
+ {
|
|
|
+ return (array)parent::getNameServers();
|
|
|
+ }
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+ /** @var AWSRoute53ResponseInterface $zones */
|
|
|
+ $zones = $this->connection->listZonesByName($this->domain);
|
|
|
+ if( $zones->getResponseType() === 'error' )
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+ $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
+ if( !$zone )
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException('Zone name is not valid!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+ $hostedZone = json_decode(json_encode($this->connection->getHostedZoneById($zone)->getParsedResponseBody()), true);
|
|
|
+ return (array)$hostedZone['DelegationSet']['NameServers']['NameServer'];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getRecords($recordType = false)
|
|
|
+ {
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+
|
|
|
+ $zone = $this->getZone();
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $records */
|
|
|
+ $records = $this->connection->listRecords($zone);
|
|
|
+ if($records->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($records->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $availableTypes = $recordType ? [$recordType] : $this->availableTypes;
|
|
|
+
|
|
|
+ $records = AwsRouteHelpers\AWSRoute53ResponseParseHelper::prepareRecordList($records->getParsedResponseBody(), $availableTypes, $this->config['soa_edit'] === 'on');
|
|
|
+
|
|
|
+ return array_map(function( dns\record\Record $record ) {
|
|
|
+ return $record;
|
|
|
+ }, $records);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function addRecord(dns\record\Record $record)
|
|
|
+ {
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+
|
|
|
+ $zone = $this->getZone();
|
|
|
+
|
|
|
+ $rrSets = $this->buildRRSets($this->getRecords());
|
|
|
+
|
|
|
+ //synchronization purposes - modifying record names to match AWS standards - shouldn't change workflow of Route53 module
|
|
|
+ $record->name = $this->prepareNameForSynchro($record->name, $this->domain);
|
|
|
+
|
|
|
+ if($record->type == 'TXT')
|
|
|
+ {
|
|
|
+ $this->explodeTxtRdata($record);
|
|
|
+ }
|
|
|
+
|
|
|
+ if( ($index = $this->findMatchingRecordSet($rrSets, $record)) !== false )
|
|
|
+ {
|
|
|
+ /** @var dns\record\RRSet $rrSet */
|
|
|
+ $rrSet = $rrSets[$index];
|
|
|
+ $rrSet->setTtl($record->ttl);
|
|
|
+ $rrSet->pushRecord($record);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $rrSet = new dns\record\RRSet($record->name, $record->type, $record->ttl, [$record]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $response = $this->connection->updateRRSet($rrSet, $zone,$this->gatAliasTypeIfRequired($record));
|
|
|
+ if( $response->getResponseType() === 'error' )
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($response->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->resetConnection();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function editRecord(dns\record\Record $record)
|
|
|
+ {
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+ $record->name = IdnaHelper::idnaEncode($record->name);
|
|
|
+ $zone = $this->getZone();
|
|
|
+ $rrSets = $this->buildRRSets($this->getRecords());
|
|
|
+
|
|
|
+ //Record RRSet based on line property
|
|
|
+ if( ($recordToDeleteIndex = $this->findRecordInRecordSets($rrSets, $record)) !== false )
|
|
|
+ {
|
|
|
+ //RRSet Changed
|
|
|
+ if( $rrSets[$recordToDeleteIndex]->getName() !== $record->name )
|
|
|
+ {
|
|
|
+ //RRSet exist so we just push
|
|
|
+ if( ($recordToAddIntex = $this->findMatchingRecordSet($rrSets, $record)) !== false )
|
|
|
+ {
|
|
|
+ $rrsetToAddRecord = $rrSets[$recordToAddIntex];
|
|
|
+ $rrsetToAddRecord->pushRecord($record);
|
|
|
+ $rrsetToAddRecord->setTtl($record->ttl);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $rrsetToAddRecord = new dns\record\RRSet($record->name, $record->type, $record->ttl, [$record]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $response = $this->connection->updateRRSet($rrsetToAddRecord,$zone,$this->gatAliasTypeIfRequired($record));
|
|
|
+
|
|
|
+ if($response->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($response->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ if( $rrSets[$recordToDeleteIndex]->countRecords() <= 1 )
|
|
|
+ {
|
|
|
+ $response = $this->connection->removeRRSet($rrSets[$recordToDeleteIndex], $zone,$this->gatAliasTypeIfRequired($record));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $rrSets[$recordToDeleteIndex]->removeRecord($record);
|
|
|
+ $response = $this->connection->updateRRSet($rrSets[$recordToDeleteIndex], $zone,$this->gatAliasTypeIfRequired($record));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //RRSet Not Changed
|
|
|
+ $rrSets[$recordToDeleteIndex]->replaceRecord($record);
|
|
|
+ $rrSets[$recordToDeleteIndex]->setTtl($record->ttl);
|
|
|
+ $response = $this->connection->updateRRSet($rrSets[$recordToDeleteIndex], $zone,$this->gatAliasTypeIfRequired($record));
|
|
|
+ }
|
|
|
+
|
|
|
+ if($response->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($response->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException('Record Not Found on server', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->resetConnection();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function deleteRecord(dns\record\Record $record)
|
|
|
+ {
|
|
|
+ $record->nameToAbsolute($this->domain);
|
|
|
+ $record->name = IdnaHelper::idnaEncode($record->name);
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+
|
|
|
+ if(strpos($record->name, $this->domain) === false) {
|
|
|
+ $record->name .= '.' . $this->domain;
|
|
|
+ }
|
|
|
+ $zone = $this->getZone();
|
|
|
+
|
|
|
+ $rrSets = $this->buildRRSets($this->getRecords());
|
|
|
+ if( ($index = $this->findMatchingRecordSet($rrSets, $record)) !== false )
|
|
|
+ {
|
|
|
+ if( $rrSets[$index]->countRecords() <= 1 )
|
|
|
+ {
|
|
|
+ $response = $this->connection->removeRRSet($rrSets[$index],$zone,$this->gatAliasTypeIfRequired($record));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $rrSets[$index]->removeRecord($record);
|
|
|
+ $response =$this->connection->updateRRSet($rrSets[$index],$zone,$this->gatAliasTypeIfRequired($record));
|
|
|
+ }
|
|
|
+
|
|
|
+ if($response->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($response->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $this->resetConnection();
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function zoneExists()
|
|
|
+ {
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $zones */
|
|
|
+ $zones = $this->connection->listZonesByName($this->domain);
|
|
|
+ if($zones->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
+
|
|
|
+ return $zone ? true : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function activateZone()
|
|
|
+ {
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+ $this->log('ACTIVATE ZONE');
|
|
|
+ if($this->zoneExists())
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException('Domain name already exists!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(empty($this->domain))
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException('Domain name is not valid!', dns\SubmoduleExceptionCodes::INVALID_PARAMETERS);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $zone */
|
|
|
+ $zone = $this->connection->createZone($this->domain, $this->config['delegation_set']);
|
|
|
+ if($zone->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($zone->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->resetConnection();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function terminateZone()
|
|
|
+ {
|
|
|
+ $records = $this->getRecords();
|
|
|
+ foreach($records as $record)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ $this->deleteRecord($record);
|
|
|
+ }
|
|
|
+ catch(DNSSubmoduleException $exc)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+ /** @var AWSRoute53ResponseInterface $zones */
|
|
|
+ $zones = $this->connection->listZonesByName($this->domain);
|
|
|
+ if($zones->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $zonesId = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
+ if($zonesId === false)
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException('Zone name is not valid!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $deleted */
|
|
|
+ $deleted = $this->connection->deleteHostedZone($zonesId);
|
|
|
+ if($deleted->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($deleted->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->resetConnection();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getZones()
|
|
|
+ {
|
|
|
+ $zones = [];
|
|
|
+ $client = \Aws\Route53\Route53Client::factory([
|
|
|
+ 'credentials' => [
|
|
|
+ 'key' => $this->config['accessKeyId'],
|
|
|
+ 'secret' => $this->config['secretAccessKey'],
|
|
|
+ ],
|
|
|
+ 'version' => '2013-04-01',
|
|
|
+ 'region' => $this->config['region']
|
|
|
+ ]);
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ $params = ['MaxItems' => 100];
|
|
|
+
|
|
|
+ if( isset($result) )
|
|
|
+ {
|
|
|
+ $params['Marker'] = $result->get('NextMarker');
|
|
|
+ }
|
|
|
+
|
|
|
+ $result = $client->listHostedZones($params);
|
|
|
+ $zones[] = array_column($result->get('HostedZones'), 'Name');
|
|
|
+ } while( $result->hasKey('NextMarker') );
|
|
|
+
|
|
|
+ $zones = array_merge(...$zones);
|
|
|
+ return array_combine($zones, array_fill(0,count($zones),''));
|
|
|
+ }
|
|
|
+
|
|
|
+ private function loadConnectionInstance()
|
|
|
+ {
|
|
|
+ if(!$this->connection)
|
|
|
+ {
|
|
|
+ $responseHandler = new AwsRouteHelpers\AWSRoute53Response();
|
|
|
+ $requestHandler = new AwsRouteHelpers\AWSRoute53Request(
|
|
|
+ $responseHandler,
|
|
|
+ $this->config['accessKeyId'],
|
|
|
+ $this->config['secretAccessKey'],
|
|
|
+ $this->config['region']
|
|
|
+ );
|
|
|
+
|
|
|
+ $apiHandler = new AwsRouteHelpers\AWSRoute53API($requestHandler);
|
|
|
+
|
|
|
+ $this->connection = $apiHandler;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public function updateRDNS($ip, $ttl = false, $value = false)
|
|
|
+ {
|
|
|
+ $revDnsZoneName = dns\utils\ReverseDNSHelper::reverseZoneName($ip);
|
|
|
+ $zoneId = $this->getRevDNSZoneID($revDnsZoneName);
|
|
|
+
|
|
|
+ if(!$zoneId)
|
|
|
+ {
|
|
|
+ $zoneId = $this->createRevDnsZone($revDnsZoneName);
|
|
|
+ }
|
|
|
+
|
|
|
+ $revRecord = dns\utils\ReverseDNSHelper::createPTRRecord($ip, $ttl, $value);
|
|
|
+ $revRecord->name .= '.'.$revDnsZoneName;
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $aRecord */
|
|
|
+ $aRecord = $this->connection->updateRecord($zoneId, $revRecord);
|
|
|
+ if($aRecord->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($aRecord->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->resetConnection();
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function removeRDNS($ip)
|
|
|
+ {
|
|
|
+ $revDnsZoneName = dns\utils\ReverseDNSHelper::reverseZoneName($ip);
|
|
|
+ $zoneId = $this->getRevDNSZoneID($revDnsZoneName);
|
|
|
+ if(!$zoneId)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $records */
|
|
|
+ $records = $this->connection->listRecords($zoneId);
|
|
|
+ if($records->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($records->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+ $recordPrev = dns\utils\ReverseDNSHelper::reverseRecordName($ip);
|
|
|
+ $recordName = $recordPrev.'.'.$revDnsZoneName;
|
|
|
+
|
|
|
+ $recordToRemove = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findPtrRecordByName($records->getParsedResponseBody(), $recordName);
|
|
|
+
|
|
|
+ if(!$recordToRemove)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $aRecord */
|
|
|
+ $aRecord = $this->connection->deleteRecord($zoneId, $recordToRemove);
|
|
|
+ if($aRecord->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($aRecord->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->resetConnection();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function getRDNSRecord($ip)
|
|
|
+ {
|
|
|
+ $revDnsZoneName = dns\utils\ReverseDNSHelper::reverseZoneName($ip);
|
|
|
+ $zoneId = $this->getRevDNSZoneID($revDnsZoneName);
|
|
|
+
|
|
|
+ if(!$zoneId)
|
|
|
+ {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $records */
|
|
|
+ $records = $this->connection->listRecords($zoneId);
|
|
|
+ if($records->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($records->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->resetConnection();
|
|
|
+ return AwsRouteHelpers\AWSRoute53ResponseParseHelper::prepareRecordList($records->getParsedResponseBody(), $this->availableTypes, $this->config['soa_edit'] === 'on');
|
|
|
+ }
|
|
|
+
|
|
|
+ private function getRevDNSZoneID($zoneName)
|
|
|
+ {
|
|
|
+ $this->loadConnectionInstance();
|
|
|
+
|
|
|
+ /** @var AWSRoute53ResponseInterface $zones */
|
|
|
+ $zones = $this->connection->listZonesByName($zoneName);
|
|
|
+ if($zones->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $zoneName);
|
|
|
+
|
|
|
+ return $zone ? : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function createRevDnsZone($revDnsZoneName)
|
|
|
+ {
|
|
|
+ /** @var AWSRoute53ResponseInterface $zone */
|
|
|
+ $zone = $this->connection->createZone($revDnsZoneName);
|
|
|
+ if($zone->getResponseType() === 'error')
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($zone->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ return AwsRouteHelpers\AWSRoute53ResponseParseHelper::getZoneIdFromCreateConfirmation($zone->getParsedResponseBody());
|
|
|
+ }
|
|
|
+
|
|
|
+ private function gatAliasTypeIfRequired($record)
|
|
|
+ {
|
|
|
+ if($record->type !== 'ALIAS')
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $dNamePos = stripos($record->name, trim($this->domain, '.'));
|
|
|
+ if(!$dNamePos && $dNamePos !== 0)
|
|
|
+ {
|
|
|
+ $record->name .= '.'.$this->domain;
|
|
|
+ }
|
|
|
+
|
|
|
+ $deafultType = 'A';
|
|
|
+
|
|
|
+ $recordsList = $this->getRecords();
|
|
|
+ foreach($recordsList as $rec)
|
|
|
+ {
|
|
|
+ $trimedName = trim($rec->name, '.');
|
|
|
+ if(($rec->name === $record->rdata->target || $trimedName === $record->rdata->target ) && $rec->type === 'AAAA')
|
|
|
+ {
|
|
|
+ return 'AAAA';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $deafultType;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function convertInputFormData(&$input)
|
|
|
+ {
|
|
|
+ AwsRouteHelpers\AWSRoute53ResponseParseHelper::convertInputFormData($input);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param dns\record\Record $record
|
|
|
+ * @return bool|dns\record\Record
|
|
|
+ * @throws DNSSubmoduleException
|
|
|
+ */
|
|
|
+ public function matchSetForRecord( dns\record\Record $record)
|
|
|
+ {
|
|
|
+ $cRecord = clone $record;
|
|
|
+ $allowedTypes = ['MX', 'A', 'AAAA', 'NS'];
|
|
|
+ if(!in_array($cRecord->type, $allowedTypes, true) )
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $basicRdata = $cRecord->rdata->toString();
|
|
|
+ $cRecord->createRDATAObject($cRecord->type);
|
|
|
+ $cRecord->rdata = null;
|
|
|
+ $recordList = $this->getRecords();
|
|
|
+ foreach($recordList as $rec)
|
|
|
+ {
|
|
|
+ if($cRecord->type === $rec->type && trim($cRecord->name, '.') === trim($rec->name, '.'))
|
|
|
+ {
|
|
|
+ if($rec->rdata->toString() === $basicRdata)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ AwsRouteHelpers\AWSRoute53ResponseParseHelper::mergeHostsRecordsForRdata($cRecord, $rec, $cRecord->type);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return $cRecord->rdata !== null ? $cRecord : false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function removeDefaultServerRecords($defaultModuleRecords)
|
|
|
+ {
|
|
|
+ if($this->config['delete_aws_ns'] !== 'on')
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ $cRecords = $this->getRecords();
|
|
|
+ foreach($cRecords as $cRecord)
|
|
|
+ {
|
|
|
+ if($cRecord->type !== 'NS')
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ $found = false;
|
|
|
+ foreach($defaultModuleRecords as $dRecord)
|
|
|
+ {
|
|
|
+ if($this->areRecordsEqual($cRecord, $dRecord))
|
|
|
+ {
|
|
|
+ $found = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if($found === false)
|
|
|
+ {
|
|
|
+ $this->deleteRecord($cRecord);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function areRecordsEqual( dns\record\Record $rec1, dns\record\Record $rec2)
|
|
|
+ {
|
|
|
+ $recAname = rtrim($rec1->name,'.');
|
|
|
+ $recBname = rtrim($rec2->name,'.');
|
|
|
+
|
|
|
+ return $recAname === $recBname &&
|
|
|
+ $rec1->type === $rec2->type &&
|
|
|
+ $rec1->ttl === $rec2->ttl &&
|
|
|
+ $rec1->rdata->toString() === $rec2->rdata->toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ private function getZone()
|
|
|
+ {
|
|
|
+ /** @var AWSRoute53ResponseInterface $zones */
|
|
|
+ $zones = $this->connection->listZonesByName($this->domain);
|
|
|
+ if( $zones->getResponseType() === 'error' )
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException($zones->getResponseMessage(), dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+
|
|
|
+ $zone = AwsRouteHelpers\AWSRoute53ResponseParseHelper::findZoneOnZoneList($zones->getParsedResponseBody(), $this->domain);
|
|
|
+ if( !$zone )
|
|
|
+ {
|
|
|
+ throw new DNSSubmoduleException('Zone name is not valid!', dns\SubmoduleExceptionCodes::COMMAND_ERROR);
|
|
|
+ }
|
|
|
+ return $zone;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function buildRRSets( array $records ): array
|
|
|
+ {
|
|
|
+ $rrsets = [];
|
|
|
+ /** @var dns\record\Record $record */
|
|
|
+ foreach($records as $record)
|
|
|
+ {
|
|
|
+ if( ($index = $this->findMatchingRecordSet($rrsets, $record)) !== false )
|
|
|
+ {
|
|
|
+ $rrsets[$index]->pushRecord($record);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $rrsets[] = new dns\record\RRSet($record->name, $record->type, $record->ttl, [$record]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $rrsets;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function findRecordInRecordSets($rrsets,dns\record\Record $record)
|
|
|
+ {
|
|
|
+ /** @var dns\record\RRSet $rrset */
|
|
|
+ foreach($rrsets as $index => $rrset)
|
|
|
+ {
|
|
|
+ if($rrset->recordExists($record))
|
|
|
+ {
|
|
|
+ return $index;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function findMatchingRecordSet( array $rrsets, dns\record\Record $record )
|
|
|
+ {
|
|
|
+ /** @var dns\record\RRSet $rrset */
|
|
|
+ foreach($rrsets as $index => $rrset)
|
|
|
+ {
|
|
|
+ if($rrset->isRecordMatchingRRset($record))
|
|
|
+ {
|
|
|
+ return $index;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function resetConnection()
|
|
|
+ {
|
|
|
+ $this->connection = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function explodeTxtRdata(&$record)
|
|
|
+ {
|
|
|
+ //AWS doesn't alllow TXT rdata record to have more than 255 chars length - need to split it to a few strings
|
|
|
+ $rdataSplitted = str_split(trim($record->rdata->txtdata, '"'), 255);
|
|
|
+ $record->rdata->txtdata = '';
|
|
|
+ foreach ($rdataSplitted as $rdataPart) {
|
|
|
+ $record->rdata->txtdata .= '"' . $rdataPart . '"';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ function prepareNameForSynchro($recordName, $domain)
|
|
|
+ {
|
|
|
+ $startsWithDot = substr($recordName, 0, 1) == '.';
|
|
|
+ $endsWithDot = substr($recordName, -1) == '.';
|
|
|
+
|
|
|
+ if ($startsWithDot)
|
|
|
+ {
|
|
|
+ $recordName = substr($recordName, 1);
|
|
|
+ }
|
|
|
+ if (!$endsWithDot)
|
|
|
+ {
|
|
|
+ $recordName = $recordName . (empty($recordName) ? '' : '.') . $domain . '.';
|
|
|
+ }
|
|
|
+ return IdnaHelper::idnaEncode($recordName);
|
|
|
+ }
|
|
|
+}
|