def test_filter_qname(self): user1, user2 = self.create_user(), self.create_user() domains = { user1: ['domain.dedyn.io', 'foobar.example'], user2: ['dedyn.io', 'desec.io'], } for user, names in domains.items(): for name in names: Domain(name=name, owner=user).save() config = { 'domain.dedyn.io': { None: ['domain.dedyn.io', 'dedyn.io'], user1: ['domain.dedyn.io'], user2: ['dedyn.io'], }, 'foo.bar.baz.foobar.example': { None: ['foobar.example'], user1: ['foobar.example'], user2: [], }, 'dedyn.io': { None: ['dedyn.io'], user1: [], user2: ['dedyn.io'], }, 'foobar.desec.io': { None: ['desec.io'], user1: [], user2: ['desec.io'], }, } config['sub.domain.dedyn.io'] = config['domain.dedyn.io'] for qname, cases in config.items(): for owner, expected in cases.items(): filter_kwargs = dict(owner=owner) if owner is not None else {} qs = Domain.objects.filter_qname( qname, **filter_kwargs).values_list('name', flat=True) self.assertListEqual(list(qs), expected)
def test_create_domain_under_public_suffix_with_private_parent(self): name = 'amazonaws.com' with self.assertPdnsRequests( self.requests_desec_domain_creation(name) [:-1]), PDNSChangeTracker(): Domain(owner=self.create_user(), name=name).save() self.assertTrue(Domain.objects.filter(name=name).exists()) # If amazonaws.com is owned by another user, we cannot register test.s4.amazonaws.com name = 'test.s4.amazonaws.com' response = self.client.post(self.reverse('v1:domain-list'), {'name': name}) self.assertStatus(response, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.data['name'][0].code, 'name_unavailable') # s3.amazonaws.com is a public suffix. Therefore, test.s3.amazonaws.com can be # registered even if the parent zone amazonaws.com is owned by another user name = 'test.s3.amazonaws.com' psl_cm = self.get_psl_context_manager('s3.amazonaws.com') with psl_cm, self.assertPdnsRequests( self.requests_desec_domain_creation(name)): response = self.client.post(self.reverse('v1:domain-list'), {'name': name}) self.assertStatus(response, status.HTTP_201_CREATED)
def assertNotRegistrable(self, domain_name, user=None): """ Raises if the given user (fresh if None) can register the given domain name. """ self.assertFalse( Domain.is_registrable(domain_name, user or self.create_user()), f'{domain_name} was expected to be not registrable for {user or "a new user"}, but was.' )
def perform_create(self, serializer): domain_name = serializer.validated_data['name'] pattern = patternDyn if self.request.user.dyn else patternNonDyn if pattern.match(domain_name) is None: ex = ValidationError( detail={ "detail": "This domain name is not well-formed, by policy.", "code": "domain-illformed" }) ex.status_code = status.HTTP_409_CONFLICT raise ex # Check if domain is a public suffix try: public_suffix = self.psl.get_public_suffix(domain_name) is_public_suffix = self.psl.is_public_suffix(domain_name) except psl_dns.exceptions.UnsupportedRule as e: # It would probably be fine to just create the domain (with the TLD acting as the # public suffix and setting both public_suffix and is_public_suffix accordingly). # However, in order to allow to investigate the situation, it's better not catch # this exception. Our error handler turns it into a 503 error and makes sure # admins are notified. raise e is_restricted_suffix = is_public_suffix and domain_name not in settings.LOCAL_PUBLIC_SUFFIXES # Generate a list of all domains connecting this one and its public suffix. # If another user owns a zone with one of these names, then the requested # domain is unavailable because it is part of the other user's zone. private_components = domain_name.rsplit(public_suffix, 1)[0].rstrip('.') private_components = private_components.split( '.') if private_components else [] private_components += [public_suffix] private_domains = [ '.'.join(private_components[i:]) for i in range(0, len(private_components) - 1) ] assert is_public_suffix or domain_name == private_domains[0] # Deny registration for non-local public suffixes and for domains covered by other users' zones queryset = Domain.objects.filter( Q(name__in=private_domains) & ~Q(owner=self.request.user)) if is_restricted_suffix or queryset.exists(): ex = ValidationError( detail={ "detail": "This domain name is unavailable.", "code": "domain-unavailable" }) ex.status_code = status.HTTP_409_CONFLICT raise ex if (self.request.user.limit_domains is not None and self.request.user.domains.count() >= self.request.user.limit_domains): ex = ValidationError( detail={ "detail": "You reached the maximum number of domains allowed for your account.", "code": "domain-limit" }) ex.status_code = status.HTTP_403_FORBIDDEN raise ex parent_domain_name = Domain.partition_name(domain_name)[1] domain_is_local = parent_domain_name in settings.LOCAL_PUBLIC_SUFFIXES try: with PDNSChangeTracker(): domain_kwargs = {'owner': self.request.user} if domain_is_local: domain_kwargs['minimum_ttl'] = 60 domain = serializer.save(**domain_kwargs) if domain_is_local: parent_domain = Domain.objects.get(name=parent_domain_name) # NOTE we need two change trackers here, as the first transaction must be committed to # pdns in order to have keys available for the delegation with PDNSChangeTracker(): parent_domain.update_delegation(domain) except PDNSException as e: if not str(e).endswith(' already exists'): raise e ex = ValidationError( detail={ "detail": "This domain name is unavailable.", "code": "domain-unavailable" }) ex.status_code = status.HTTP_400_BAD_REQUEST raise ex def send_dyn_dns_email(): content_tmpl = get_template('emails/domain-dyndns/content.txt') subject_tmpl = get_template('emails/domain-dyndns/subject.txt') from_tmpl = get_template('emails/from.txt') context = { 'domain': domain_name, 'url': 'https://update.dedyn.io/', 'username': domain_name, 'password': self.request.auth.key } email = EmailMessage(subject_tmpl.render(context), content_tmpl.render(context), from_tmpl.render(context), [self.request.user.email]) email.send() if domain.name.endswith('.dedyn.io'): send_dyn_dns_email()
def create_domain(cls, suffix=None, **kwargs): kwargs.setdefault('owner', cls.create_user()) kwargs.setdefault('name', cls.random_domain_name(suffix)) domain = Domain(**kwargs) domain.save() return domain
def createDomain(cls, owner=None, port=80): if owner is None: owner = cls.createUser(username=None) domain = Domain(name=cls.generateDomainname(), owner=owner) domain.save() return domain