def test_remove_dns_entries(self, mock_client): ds = DomainService('sundayafternoon') ds.build_cookie = Mock(return_value={'cookie': 'value'}) ds.update_cookie = Mock() getinfo_result = Mock() dns_entry1 = DnsEntry( 'testentry1', 86400, DnsEntry.TYPE_A, '127.0.0.1', ) dns_entry2 = DnsEntry( 'testentry2', 86400, DnsEntry.TYPE_A, '127.0.0.1', ) getinfo_result.dnsEntries = [ dns_entry1, dns_entry2, ] mock_client.return_value.service.getInfo.return_value = getinfo_result ds.remove_dns_entries('domain1', [dns_entry1]) mock_client.return_value.service.setDnsEntries.assert_called_with( 'domain1', [dns_entry2], )
def testEquality(self): dns_entry_one = DnsEntry('@', 300, DnsEntry.TYPE_A, '8.8.8.8') dns_entry_two = DnsEntry('@', 300, DnsEntry.TYPE_A, '8.8.8.8') self.assertEqual(dns_entry_one, dns_entry_two) dns_entry_two.expire = 600 self.assertEqual(dns_entry_one, dns_entry_two) dns_entry_two.content = '127.0.0.1' self.assertNotEqual(dns_entry_one, dns_entry_two)
def _to_dns_entry(self, _entry): return DnsEntry( self._relative_name(_entry["name"]), _entry["ttl"], _entry["type"], _entry["content"], )
def _entries_for_multiple(self, name, record): _entries = [] for value in record.values: _entries.append(DnsEntry(name, record.ttl, record._type, value)) return _entries
def _create_record(self, rtype, name, content): records = self.client.get_info(self.domain).dnsEntries if self._filter_records(records, rtype, name, content): # Nothing to do, record already exists LOGGER.debug("create_record: already exists") return True records.append( DnsEntry( **{ "name": self._relative_name(name), "record_type": rtype, "content": self._bind_format_target(rtype, content), "expire": self._get_lexicon_option("ttl"), } ) ) self.client.set_dns_entries(self.domain, records) status = ( len(self._list_records_internal(rtype, name, content, show_output=False)) >= 1 ) LOGGER.debug("create_record: %s", status) return status
def test_set_dns_entries(self, mock_client): # SETUP ds = DomainService('sundayafternoon') ds.build_cookie = Mock(return_value={"cookie": "value"}) ds.update_cookie = Mock() i = mock_client.return_value i.service.setDnsEntries.return_value = None dns_entry = DnsEntry('testentry', 86400, DnsEntry.TYPE_A, '127.0.0.1') # CALL result = ds.set_dns_entries('domain1', [ dns_entry, ]) # VERIFY ds.build_cookie.assert_called_with(mode=MODE_RW, method='setDnsEntries', parameters=('domain1', [ dns_entry, ])) ds.update_cookie.assert_called_with({"cookie": "value"}) i.service.setDnsEntries.assert_called_with('domain1', [ dns_entry, ])
def _entries_for_TXT(self, name, record): _entries = [] for value in record.values: value = value.replace('\\;', ';') _entries.append(DnsEntry(name, record.ttl, record._type, value)) return _entries
def _entries_for_MX(self, name, record): _entries = [] for value in record.values: content = "{} {}".format(value.preference, value.exchange) _entries.append(DnsEntry(name, record.ttl, record._type, content)) return _entries
def _entries_for_CAA(self, name, record): _entries = [] for value in record.values: content = "{} {} {}".format(value.flags, value.tag, value.value) _entries.append(DnsEntry(name, record.ttl, record._type, content)) return _entries
def _entries_for_SRV(self, name, record): _entries = [] for value in record.values: content = "{} {} {} {}".format(value.priority, value.weight, value.port, value.target) _entries.append(DnsEntry(name, record.ttl, record._type, content)) return _entries
def update_a_records(config_domains, avail_domains, expire_time, domain_service): domain_records = defaultdict(set) # Create inventory of which records to update for each domain for fqdn in config_domains: parts = fqdn.strip().rsplit('.', 2) if len(parts) < 2: raise ConfigError("Invalid domain in configuration: '{}'".format(fqdn)) elif len(parts) == 2: record, (domain, tld) = '@', parts else: record, domain, tld = parts domain = "{}.{}".format(domain, tld) if domain not in avail_domains: raise ConfigError("Configured domain '{}' does not belong to this account".format(domain)) log.debug("A record to update: '{}' on domain '{}'".format(record, domain)) domain_records[domain].add(record) if not domain_records: log.debug("No A records configured to update") return ipv4 = get_ipv4() log.debug("Found external IPv4 address {}".format(ipv4)) updated = False # Update records for domain, records in domain_records.items(): entries = domain_service.get_info(domain).dnsEntries # Update existing entries for entry in entries: if entry.type != 'A': continue if entry.name not in records: continue log.debug("Found relevant A record on {}: {}".format(domain, entry)) records.remove(entry.name) if entry.content == ipv4: log.debug("A record for '{}' on domain '{}' is already up to date".format(entry.name, domain)) continue else: log.info("Updating A record for '{}' on domain '{}' to '{}'".format(entry.name, domain, ipv4)) entry.content = ipv4 updated = True # Create new entries for new_record in records: log.info("Creating new A record for '{}' on domain '{}' with content '{}' and expiry {}".format(new_record, domain, ipv4, expire_time)) entries.append(DnsEntry(new_record, expire_time, 'A', ipv4)) updated = True # Set new entries via API if needed if updated: domain_service.set_dns_entries(domain, entries)
def _entries_for_SSHFP(self, name, record): _entries = [] for value in record.values: content = "{} {} {}".format(value.algorithm, value.fingerprint_type, value.fingerprint) _entries.append(DnsEntry(name, record.ttl, record._type, content)) return _entries
def setUp(self): self.domain_service = mock.MagicMock() with open(KEY_FILE, 'w') as key_file: key_file.write('''-----BEGIN RSA PRIVATE KEY----- foobar -----END RSA PRIVATE KEY-----''') self.transip_client = _TransipClient(username=USERNAME, key_file=KEY_FILE) self.transip_client.domain_service = self.domain_service self.domain_service.get_domain_names.return_value = ['example.com'] self.correct_entry1 = DnsEntry(name='record1', record_type='A', content='127.0.0.1', expire=1) self.correct_entry2 = DnsEntry(name='record2', record_type='TXT', content='f00b4r', expire=1) self.add_record = DnsEntry(name='test.test', record_type='TXT', content='new record', expire=1)
def update_dns(domain_service, args): """ Adds, updates or deletes a DNS entry through the API :param domain_service: an initialized DomainService object :param args: arguments object from argparse """ try: dns_entries = domain_service.get_info(args.domain_name).dnsEntries except WebFault as err: print(err) sys.exit(1) number_of_entries = len(dns_entries) for entry in dns_entries: if args.add_dns_entry and entry.name == args.entry_name and entry.type == args.entry_type and \ entry.content == args.entry_content: print('The DNS entry already exists.') sys.exit(1) elif args.update_dns_entry and entry.name == args.entry_name and entry.type == args.entry_type: dns_entries.remove(entry) elif args.delete_dns_entry and entry.name == args.entry_name and entry.type == args.entry_type and \ entry.expire == args.entry_expire and entry.content == args.entry_content: dns_entries.remove(entry) if args.update_dns_entry or args.delete_dns_entry: if number_of_entries == len(dns_entries): print('The DNS entry was not found.') sys.exit(1) if args.add_dns_entry or args.update_dns_entry: dns_entries.append( DnsEntry(args.entry_name, args.entry_expire, args.entry_type, args.entry_content)) try: result = domain_service.set_dns_entries(args.domain_name, dns_entries) except WebFault as err: print(err) sys.exit(1) if result is None: print('Request finished successfully.') else: print(result)
def add_txt_record(self, domain_name, record_name, record_content): """ Add a TXT record using the supplied information. :param str domain_name: The domain to use to associate the record with. :param str record_name: The record name (typically beginning with '_acme-challenge.'). :param str record_content: The record content (typically the challenge validation). :raises certbot.errors.PluginError: if an error occurs communicating with the Transip API """ try: domain = self._find_domain(domain_name) except suds.WebFault as error: self.logger.error('Error finding domain using the Transip API: %s', error) raise errors.PluginError( 'Error finding domain using the Transip API: {0}'.format( error)) domain_records = self._get_dns_entries(domain) try: new_record = DnsEntry( name=self._compute_record_name(domain, record_name), record_type='TXT', content=record_content, expire=1, ) except suds.WebFault as error: self.logger.error( 'Error getting DNS records using the Transip API: %s', error) return domain_records.append(new_record) try: self.domain_service.set_dns_entries(domain_name=domain, dns_entries=domain_records) self.logger.info('Successfully added TXT record') except suds.WebFault as error: self.logger.error( 'Error adding TXT record using the Transip API: %s', error) raise errors.PluginError( 'Error adding TXT record using the Transip API: {0}'.format( error))
def get_info(self, domain_name): """ Retrieves information about the requested domain-name. :param domain_name: str :rtype: transip.service.objects.Domain """ cookie = self.build_cookie(mode=MODE_RO, method='getInfo', parameters=[domain_name]) self.update_cookie(cookie) # Perform the call result = self.soap_client.service.getInfo(domain_name) # Parse the result to well-known objects new_dns_entries = [] for dnsentry in result.dnsEntries: if dnsentry.__class__.__name__ == 'DnsEntry': new_dns_entries.append(DnsEntry(dnsentry.name, dnsentry.expire, dnsentry.type, dnsentry.content)) result.dnsEntries = new_dns_entries return result
def create_record(self, type, name, content): records = self.client.get_info(self.domain).dnsEntries if self._filter_records(records, type, name, content): # Nothing to do, record already exists LOGGER.debug('create_record: already exists') return True records.append(DnsEntry(**{ "name": self._relative_name(name), "record_type": type, "content": self._bind_format_target(type, content), "expire": self._get_lexicon_option('ttl') })) self.client.set_dns_entries(self.domain, records) status = len(self.list_records( type, name, content, show_output=False)) >= 1 LOGGER.debug('create_record: %s', status) return status
def mockup(self, records): provider = TransipProvider('', '', '') _dns_entries = [] for record in records: if record._type in provider.SUPPORTS: entries_for = getattr(provider, '_entries_for_{}'.format(record._type)) # Root records have '@' as name name = record.name if name == '': name = provider.ROOT_RECORD _dns_entries.extend(entries_for(name, record)) # NS is not supported as a DNS Entry, # so it should cover the if statement _dns_entries.append( DnsEntry('@', '3600', 'NS', 'ns01.transip.nl.')) self.mockupEntries = _dns_entries
def test_get_info(self, mock_client): # SETUP ds = DomainService(login='******') ds.build_cookie = Mock(return_value={"cookie": "value"}) ds.update_cookie = Mock() i = mock_client.return_value getinfo_result = Mock() getinfo_result.dnsEntries = [ DnsEntry('testentry', 86400, DnsEntry.TYPE_A, '127.0.0.1') ] i.service.getInfo.return_value = getinfo_result # CALL result = ds.get_info('example.com') # VERIFY ds.build_cookie.assert_called_with(mode=MODE_RO, method='getInfo', parameters=['example.com']) ds.update_cookie.assert_called_with({"cookie": "value"}) i.service.getInfo.assert_called_with('example.com') self.assertEqual(result, getinfo_result)
def mockup(self, records): provider = TransipProvider('', '', '') _dns_entries = [] for record in records: if record._type in provider.SUPPORTS: entries_for = getattr(provider, '_entries_for_{}'.format(record._type)) # Root records have '@' as name name = record.name if name == '': name = provider.ROOT_RECORD _dns_entries.extend(entries_for(name, record)) # Add a non-supported type # so it triggers the "is supported" (transip.py:115) check and # give 100% code coverage _dns_entries.append( DnsEntry('@', '3600', 'BOGUS', 'ns01.transip.nl.')) self.mockupEntries = _dns_entries
def _to_dns_entry(self, _entry): return DnsEntry(self._relative_name(_entry['name']), _entry['ttl'], _entry['type'], _entry['content'])
def _entries_for_single(self, name, record): return [DnsEntry(name, record.ttl, record._type, record.value)]
def build_record(self, domain, name, challenge): return DnsEntry(name[:-(len(domain) + 1)], 1, DnsEntry.TYPE_TXT, challenge)