mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-15 14:04:10 +02:00
Merge pull request #2305 from cisagov/rh/2273-ds-record-change
ISSUE #2273: Add logging for DS data changes
This commit is contained in:
commit
7c74eca92f
3 changed files with 80 additions and 16 deletions
18
src/registrar/migrations/0102_domain_dsdata_last_change.py
Normal file
18
src/registrar/migrations/0102_domain_dsdata_last_change.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 4.2.10 on 2024-06-14 19:26
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("registrar", "0101_domaininformation_cisa_representative_first_name_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="domain",
|
||||||
|
name="dsdata_last_change",
|
||||||
|
field=models.TextField(blank=True, help_text="Record of the last change event for ds data", null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -40,6 +40,8 @@ from .utility.time_stamped_model import TimeStampedModel
|
||||||
|
|
||||||
from .public_contact import PublicContact
|
from .public_contact import PublicContact
|
||||||
|
|
||||||
|
from .user_domain_role import UserDomainRole
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -672,11 +674,29 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
remRequest = commands.UpdateDomain(name=self.name)
|
remRequest = commands.UpdateDomain(name=self.name)
|
||||||
remExtension = commands.UpdateDomainDNSSECExtension(**remParams)
|
remExtension = commands.UpdateDomainDNSSECExtension(**remParams)
|
||||||
remRequest.add_extension(remExtension)
|
remRequest.add_extension(remExtension)
|
||||||
|
dsdata_change_log = ""
|
||||||
|
|
||||||
|
# Get the user's email
|
||||||
|
user_domain_role = UserDomainRole.objects.filter(domain=self).first()
|
||||||
|
user_email = user_domain_role.user.email if user_domain_role else "unknown user"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if "dsData" in _addDnssecdata and _addDnssecdata["dsData"] is not None:
|
added_record = "dsData" in _addDnssecdata and _addDnssecdata["dsData"] is not None
|
||||||
|
deleted_record = "dsData" in _remDnssecdata and _remDnssecdata["dsData"] is not None
|
||||||
|
|
||||||
|
if added_record:
|
||||||
registry.send(addRequest, cleaned=True)
|
registry.send(addRequest, cleaned=True)
|
||||||
if "dsData" in _remDnssecdata and _remDnssecdata["dsData"] is not None:
|
dsdata_change_log = f"{user_email} added a DS data record"
|
||||||
|
if deleted_record:
|
||||||
registry.send(remRequest, cleaned=True)
|
registry.send(remRequest, cleaned=True)
|
||||||
|
if dsdata_change_log != "": # if they add and remove a record at same time
|
||||||
|
dsdata_change_log = f"{user_email} added and deleted a DS data record"
|
||||||
|
else:
|
||||||
|
dsdata_change_log = f"{user_email} deleted a DS data record"
|
||||||
|
if dsdata_change_log != "":
|
||||||
|
self.dsdata_last_change = dsdata_change_log
|
||||||
|
self.save() # audit log will now record this as a change
|
||||||
|
|
||||||
except RegistryError as e:
|
except RegistryError as e:
|
||||||
logger.error("Error updating DNSSEC, code was %s error was %s" % (e.code, e))
|
logger.error("Error updating DNSSEC, code was %s error was %s" % (e.code, e))
|
||||||
raise e
|
raise e
|
||||||
|
@ -1057,6 +1077,12 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
verbose_name="first ready on",
|
verbose_name="first ready on",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dsdata_last_change = TextField(
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
help_text="Record of the last change event for ds data",
|
||||||
|
)
|
||||||
|
|
||||||
def isActive(self):
|
def isActive(self):
|
||||||
return self.state == Domain.State.CREATED
|
return self.state == Domain.State.CREATED
|
||||||
|
|
||||||
|
|
|
@ -1901,12 +1901,8 @@ class TestRegistrantDNSSEC(MockEppLib):
|
||||||
3 - setter adds the UpdateDNSSECExtension extension to the command
|
3 - setter adds the UpdateDNSSECExtension extension to the command
|
||||||
4 - setter causes the getter to call info domain on next get from cache
|
4 - setter causes the getter to call info domain on next get from cache
|
||||||
5 - getter properly parses dnssecdata from InfoDomain response and sets to cache
|
5 - getter properly parses dnssecdata from InfoDomain response and sets to cache
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# need to use a separate patcher and side_effect for this test, as
|
|
||||||
# response from InfoDomain must be different for different iterations
|
|
||||||
# of the same command
|
|
||||||
def side_effect(_request, cleaned):
|
def side_effect(_request, cleaned):
|
||||||
if isinstance(_request, commands.InfoDomain):
|
if isinstance(_request, commands.InfoDomain):
|
||||||
if mocked_send.call_count == 1:
|
if mocked_send.call_count == 1:
|
||||||
|
@ -1924,17 +1920,30 @@ class TestRegistrantDNSSEC(MockEppLib):
|
||||||
mocked_send = patcher.start()
|
mocked_send = patcher.start()
|
||||||
mocked_send.side_effect = side_effect
|
mocked_send.side_effect = side_effect
|
||||||
domain, _ = Domain.objects.get_or_create(name="dnssec-dsdata.gov")
|
domain, _ = Domain.objects.get_or_create(name="dnssec-dsdata.gov")
|
||||||
|
|
||||||
|
# Check initial dsdata_last_change value (should be None)
|
||||||
|
initial_change = domain.dsdata_last_change
|
||||||
|
|
||||||
|
# Adding dnssec data
|
||||||
domain.dnssecdata = self.dnssecExtensionWithDsData
|
domain.dnssecdata = self.dnssecExtensionWithDsData
|
||||||
# get the DNS SEC extension added to the UpdateDomain command and
|
|
||||||
|
# Check dsdata_last_change is updated after adding data
|
||||||
|
domain = Domain.objects.get(name="dnssec-dsdata.gov")
|
||||||
|
self.assertIsNotNone(domain.dsdata_last_change)
|
||||||
|
|
||||||
|
self.assertNotEqual(domain.dsdata_last_change, initial_change)
|
||||||
|
|
||||||
|
# Get the DNS SEC extension added to the UpdateDomain command and
|
||||||
# verify that it is properly sent
|
# verify that it is properly sent
|
||||||
# args[0] is the _request sent to registry
|
# args[0] is the _request sent to registry
|
||||||
args, _ = mocked_send.call_args
|
args, _ = mocked_send.call_args
|
||||||
# assert that the extension on the update matches
|
# Assert that the extension on the update matches
|
||||||
self.assertEquals(
|
self.assertEquals(
|
||||||
args[0].extensions[0],
|
args[0].extensions[0],
|
||||||
self.createUpdateExtension(self.dnssecExtensionWithDsData),
|
self.createUpdateExtension(self.dnssecExtensionWithDsData),
|
||||||
)
|
)
|
||||||
# test that the dnssecdata getter is functioning properly
|
|
||||||
|
# Test that the dnssecdata getter is functioning properly
|
||||||
dnssecdata_get = domain.dnssecdata
|
dnssecdata_get = domain.dnssecdata
|
||||||
mocked_send.assert_has_calls(
|
mocked_send.assert_has_calls(
|
||||||
[
|
[
|
||||||
|
@ -2129,13 +2138,9 @@ class TestRegistrantDNSSEC(MockEppLib):
|
||||||
2 - first setter calls UpdateDomain command
|
2 - first setter calls UpdateDomain command
|
||||||
3 - second setter calls InfoDomain command again
|
3 - second setter calls InfoDomain command again
|
||||||
3 - setter then calls UpdateDomain command
|
3 - setter then calls UpdateDomain command
|
||||||
4 - setter adds the UpdateDNSSECExtension extension to the command with rem
|
4 - setter adds the UpdateDNSSExtension extension to the command with rem
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# need to use a separate patcher and side_effect for this test, as
|
|
||||||
# response from InfoDomain must be different for different iterations
|
|
||||||
# of the same command
|
|
||||||
def side_effect(_request, cleaned):
|
def side_effect(_request, cleaned):
|
||||||
if isinstance(_request, commands.InfoDomain):
|
if isinstance(_request, commands.InfoDomain):
|
||||||
if mocked_send.call_count == 1:
|
if mocked_send.call_count == 1:
|
||||||
|
@ -2153,10 +2158,25 @@ class TestRegistrantDNSSEC(MockEppLib):
|
||||||
mocked_send = patcher.start()
|
mocked_send = patcher.start()
|
||||||
mocked_send.side_effect = side_effect
|
mocked_send.side_effect = side_effect
|
||||||
domain, _ = Domain.objects.get_or_create(name="dnssec-dsdata.gov")
|
domain, _ = Domain.objects.get_or_create(name="dnssec-dsdata.gov")
|
||||||
# dnssecdata_get_initial = domain.dnssecdata # call to force initial mock
|
|
||||||
# domain._invalidate_cache()
|
# Initial setting of dnssec data
|
||||||
domain.dnssecdata = self.dnssecExtensionWithDsData
|
domain.dnssecdata = self.dnssecExtensionWithDsData
|
||||||
|
|
||||||
|
# Check dsdata_last_change is updated
|
||||||
|
domain = Domain.objects.get(name="dnssec-dsdata.gov")
|
||||||
|
self.assertIsNotNone(domain.dsdata_last_change)
|
||||||
|
|
||||||
|
initial_change = domain.dsdata_last_change
|
||||||
|
|
||||||
|
# Remove dnssec data
|
||||||
domain.dnssecdata = self.dnssecExtensionRemovingDsData
|
domain.dnssecdata = self.dnssecExtensionRemovingDsData
|
||||||
|
|
||||||
|
# Check that dsdata_last_change is updated again
|
||||||
|
domain = Domain.objects.get(name="dnssec-dsdata.gov")
|
||||||
|
self.assertIsNotNone(domain.dsdata_last_change)
|
||||||
|
|
||||||
|
self.assertNotEqual(domain.dsdata_last_change, initial_change)
|
||||||
|
|
||||||
# get the DNS SEC extension added to the UpdateDomain command and
|
# get the DNS SEC extension added to the UpdateDomain command and
|
||||||
# verify that it is properly sent
|
# verify that it is properly sent
|
||||||
# args[0] is the _request sent to registry
|
# args[0] is the _request sent to registry
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue