diff --git a/api/desecapi/tests/test_token_domain_policy.py b/api/desecapi/tests/test_token_domain_policy.py index 1ad1d047c..efe635348 100644 --- a/api/desecapi/tests/test_token_domain_policy.py +++ b/api/desecapi/tests/test_token_domain_policy.py @@ -721,3 +721,34 @@ def test_auto_policy_from_creation(self): token = models.Token.objects.get(pk=response.data["id"]) self.assertEqual(token.tokendomainpolicy_set.count(), 1) self.assertFalse(token.get_policy().perm_write) + + def test_create_domain(self): + self.token.auto_policy = True + self.token.save() + self.token_manage.perm_create_domain = True + self.token_manage.save() + + name_auto = "domain.example" + name_other = "other.example" + with self.assertRequests(self.requests_desec_domain_creation(name_other)): + response = self.client._request( + self.client.post, + self.reverse("v1:domain-list"), + using=self.token_manage, + data={"name": name_other}, + ) + self.assertStatus(response, status.HTTP_201_CREATED) + with self.assertRequests(self.requests_desec_domain_creation(name_auto)): + response = self.client._request( + self.client.post, + self.reverse("v1:domain-list"), + using=self.token, + data={"name": name_auto}, + ) + self.assertStatus(response, status.HTTP_201_CREATED) + + self.assertEqual(self.token.tokendomainpolicy_set.count(), 2) + rrset = models.RRset(domain=models.Domain.objects.get(name=name_auto)) + self.assertTrue(self.token.get_policy(rrset).perm_write) + rrset = models.RRset(domain=models.Domain.objects.get(name=name_other)) + self.assertFalse(self.token.get_policy(rrset).perm_write) diff --git a/api/desecapi/views/domains.py b/api/desecapi/views/domains.py index 829e729ad..6b305ba07 100644 --- a/api/desecapi/views/domains.py +++ b/api/desecapi/views/domains.py @@ -103,6 +103,10 @@ def perform_create(self, serializer): ) with PDNSChangeTracker(): domain = serializer.save(owner=self.request.user) + if self.request.auth.auto_policy: + self.request.auth.tokendomainpolicy_set.create( + domain=domain, perm_write=True + ) # TODO this line raises if the local public suffix is not in our database! PDNSChangeTracker.track(lambda: self.auto_delegate(domain)) diff --git a/docs/auth/tokens.rst b/docs/auth/tokens.rst index 7e84f419c..014ca1b4a 100644 --- a/docs/auth/tokens.rst +++ b/docs/auth/tokens.rst @@ -35,6 +35,7 @@ A JSON object representing a token has the following structure:: "0.0.0.0/0", "::/0" ], + "auto_policy": false, "max_age": "365 00:00:00", "max_unused_period": null, "token": "4pnk7u-NHvrEkFzrhFDRTjGFyX_S" @@ -50,6 +51,17 @@ Field details: order to successfully authenticate with the token. Both IPv4 and IPv6 are supported. Defaults to ``0.0.0.0/0, ::/0`` (no restriction). +``auto_policy`` + :Access mode: read, write + :Type: boolean + + When using this token to create a domain, automatically configure a + permissive scoping policy for it (``perm_write=true``). Requires a + restrictive default policy (``perm_write=false``), which is created + automatically when setting this flag. Cannot be set to true if a + permissive default policy exists. For details, see + :ref:`token scoping policies`. + ``created`` :Access mode: read-only :Type: timestamp @@ -173,6 +185,7 @@ Note that the name and other fields are optional. The server will reply with "0.0.0.0/0", "::/0" ], + "auto_policy": false, "token": "4pnk7u-NHvrEkFzrhFDRTjGFyX_S" } @@ -350,6 +363,8 @@ match only RRsets with an identical wildcard ``subname``. RRsets for which no more specific policy is configured are eventually caught by the token's default policy. It is therefore required to create such a default policy before any more specific policies can be created on a given token. +A domain-wide permissive policy can be configured automatically during domain +creation by setting the token's ``auto_policy`` flag. Tokens with at least one policy are considered *restricted*, with their DNS record management capabilities limited as per policy configuration.