This is an automated email from the ASF dual-hosted git repository.

rawlin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new a663e7a  TR should support aggressive NSEC queries (#6648)
a663e7a is described below

commit a663e7a36814e45e2ee8ffbf7b0c7aa6111a0494
Author: Srijeet Chatterjee <[email protected]>
AuthorDate: Fri Apr 1 13:01:09 2022 -0600

    TR should support aggressive NSEC queries (#6648)
    
    * wip
    
    * TR should support aggressive NSEC queries
    
    * code review fix
---
 CHANGELOG.md                                       |   1 +
 .../traffic_router/core/dns/ZoneManager.java       |  36 ++++++-
 .../core/dns/ZoneManagerUnitTest.java              | 110 ++++++++++++++++++++-
 3 files changed, 138 insertions(+), 9 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b65e77b..ecd2dbf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - [#6590](https://github.com/apache/trafficcontrol/pull/6590) Python client: 
Corrected parameter name in decorator for get\_parameters\_by\_profile\_id
 - [#6368](https://github.com/apache/trafficcontrol/pull/6368) Fixed validation 
response message from `/acme_accounts`
 - [#6603](https://github.com/apache/trafficcontrol/issues/6603) Fixed users 
with "admin" "Priv Level" not having Permission to view or delete DNSSEC keys.
+- Fixed Traffic Router to handle aggressive NSEC correctly.
 - [#6626](https://github.com/apache/trafficcontrol/pull/6626) Fixed t3c 
Capabilities request failure issue which could result in malformed config.
 - [#6370](https://github.com/apache/trafficcontrol/pull/6370) Fixed docs for 
`POST` and response code for `PUT` to `/acme_accounts` endpoint
 - Only `operations` and `admin` roles should have the 
`DELIVERY-SERVICE:UPDATE` permission.
diff --git 
a/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/dns/ZoneManager.java
 
b/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/dns/ZoneManager.java
index 149c7fd..d1a2c9a 100644
--- 
a/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/dns/ZoneManager.java
+++ 
b/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/dns/ZoneManager.java
@@ -940,7 +940,7 @@ public class ZoneManager extends Resolver {
                        final DNSRouteResult result = 
trafficRouter.route(request, track);
 
                        if (result != null) {
-                               final Zone dynamicZone = 
fillDynamicZone(dynamicZoneCache, staticZone, request, result);
+                               final Zone dynamicZone = 
fillDynamicZone(getDynamicZoneCache(), staticZone, request, result);
                                track.setResultCode(dynamicZone, 
request.getName(), request.getQueryType());
                                if (result.getDeliveryService() == null) {
                                        builder.deliveryServiceXmlIds(null);
@@ -972,16 +972,23 @@ public class ZoneManager extends Resolver {
                try {
                        boolean nsSeen = false;
                        final List<Record> records = new ArrayList<>();
-
+                       String dsRoutingName = null;
+                       boolean routingNameNSECSeen = false;
                        for (final InetRecord address : result.getAddresses()) {
                                final DeliveryService ds = 
result.getDeliveryService();
                                Name name = request.getName();
 
+                               if (ds != null && ds.getRoutingName() != null) {
+                                       dsRoutingName = ds.getRoutingName();
+                               }
                                if (address.getType() == Type.NS) {
                                        name = staticZone.getOrigin();
                                } else if (ds != null && (address.getType() == 
Type.A || address.getType() == Type.AAAA)) {
                                        final String routingName = 
ds.getRoutingName();
                                        name = new Name(routingName, 
staticZone.getOrigin()); // routingname.ds.cdn.tld
+                               } else if (ds != null && address.getType() == 
Type.NSEC && dsRoutingName != null &&
+                                               address.getTarget().equals(new 
Name(dsRoutingName, staticZone.getOrigin()).toString())) {
+                                       routingNameNSECSeen = true;
                                }
 
                                final Record record = createRecord(name, 
address);
@@ -989,7 +996,6 @@ public class ZoneManager extends Resolver {
                                if (record != null) {
                                        records.add(record);
                                }
-
                                if (record instanceof NSRecord) {
                                        nsSeen = true;
                                }
@@ -1009,7 +1015,20 @@ public class ZoneManager extends Resolver {
                                                continue;
                                        }
 
-                                       records.add(r);
+                                       if (r.getType() == Type.NSEC && 
r.getName().toString().equals(staticZone.getOrigin().toString()) && 
dsRoutingName != null) {
+                                               final Name dsFQDN = new 
Name(dsRoutingName, staticZone.getOrigin());
+                                               if (r instanceof NSECRecord) {
+                                                       final NSECRecord 
removeRec = new NSECRecord(dsFQDN, r.getDClass(), r.getTTL(), ((NSECRecord) 
r).getNext(), ((NSECRecord) r).getTypes());
+                                                       if 
(dsFQDN.compareTo(removeRec.getNext()) < 0 && !routingNameNSECSeen) {
+                                                               
records.add(removeRec);
+                                                               
routingNameNSECSeen = true;
+                                                       } else {
+                                                               records.add(r);
+                                                       }
+                                               }
+                                       } else {
+                                               records.add(r);
+                                       }
                                }
 
                        }
@@ -1020,7 +1039,7 @@ public class ZoneManager extends Resolver {
                                }
 
                                try {
-                                       final ZoneKey zoneKey = 
signatureManager.generateDynamicZoneKey(staticZone.getOrigin(), records, 
request.isDnssec());
+                                       final ZoneKey zoneKey = 
getSignatureManager().generateDynamicZoneKey(staticZone.getOrigin(), records, 
request.isDnssec());
                                        final Zone zone = dzc.get(zoneKey);
                                        return zone;
                                } catch (ExecutionException e) {
@@ -1199,4 +1218,11 @@ public class ZoneManager extends Resolver {
        public CacheStats getDynamicCacheStats() {
                return dynamicZoneCache.stats();
        }
+
+       public static SignatureManager getSignatureManager() {
+               return signatureManager;
+       }
+       public static LoadingCache<ZoneKey, Zone> getDynamicZoneCache() {
+               return dynamicZoneCache;
+       }
 }
diff --git 
a/traffic_router/core/src/test/java/org/apache/traffic_control/traffic_router/core/dns/ZoneManagerUnitTest.java
 
b/traffic_router/core/src/test/java/org/apache/traffic_control/traffic_router/core/dns/ZoneManagerUnitTest.java
index 69cca2f..5445622 100644
--- 
a/traffic_router/core/src/test/java/org/apache/traffic_control/traffic_router/core/dns/ZoneManagerUnitTest.java
+++ 
b/traffic_router/core/src/test/java/org/apache/traffic_control/traffic_router/core/dns/ZoneManagerUnitTest.java
@@ -15,7 +15,17 @@
 
 package org.apache.traffic_control.traffic_router.core.dns;
 
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import org.apache.traffic_control.traffic_router.core.ds.DeliveryService;
 import org.apache.traffic_control.traffic_router.core.edge.CacheRegister;
+import org.apache.traffic_control.traffic_router.core.edge.InetRecord;
+import org.apache.traffic_control.traffic_router.core.request.DNSRequest;
+import org.apache.traffic_control.traffic_router.core.router.DNSRouteResult;
 import org.apache.traffic_control.traffic_router.core.router.StatTracker;
 import 
org.apache.traffic_control.traffic_router.core.router.StatTracker.Track.ResultType;
 import 
org.apache.traffic_control.traffic_router.core.router.TrafficRouterManager;
@@ -24,6 +34,7 @@ import 
org.apache.traffic_control.traffic_router.core.router.TrafficRouter;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.stubbing.Answer;
 import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PowerMockIgnore;
 import org.powermock.core.classloader.annotations.PrepareForTest;
@@ -38,8 +49,11 @@ import org.xbill.DNS.SOARecord;
 import org.xbill.DNS.SetResponse;
 import org.xbill.DNS.Type;
 import org.xbill.DNS.Zone;
+import org.xbill.DNS.NSRecord;
+import org.xbill.DNS.CNAMERecord;
 
 import java.net.InetAddress;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
@@ -57,18 +71,20 @@ import static 
org.powermock.api.mockito.PowerMockito.whenNew;
 @PowerMockIgnore("javax.management.*")
 public class ZoneManagerUnitTest {
     ZoneManager zoneManager;
-
+    TrafficRouter trafficRouter;
+    SignatureManager signatureManager;
+    CacheRegister cacheRegister;
     @Before
     public void before() throws Exception {
-        TrafficRouter trafficRouter = mock(TrafficRouter.class);
-        CacheRegister cacheRegister = mock(CacheRegister.class);
+        trafficRouter = mock(TrafficRouter.class);
+        cacheRegister = mock(CacheRegister.class);
         when(trafficRouter.getCacheRegister()).thenReturn(cacheRegister);
 
         PowerMockito.spy(ZoneManager.class);
         PowerMockito.stub(PowerMockito.method(ZoneManager.class, 
"initTopLevelDomain")).toReturn(null);
         PowerMockito.stub(PowerMockito.method(ZoneManager.class, 
"initZoneCache")).toReturn(null);
 
-        SignatureManager signatureManager = 
PowerMockito.mock(SignatureManager.class);
+        signatureManager = PowerMockito.mock(SignatureManager.class);
         whenNew(SignatureManager.class).withArguments(any(ZoneManager.class), 
any(CacheRegister.class), any(TrafficOpsUtils.class), 
any(TrafficRouterManager.class)).thenReturn(signatureManager);
 
         zoneManager = spy(new ZoneManager(trafficRouter, new StatTracker(), 
null, mock(TrafficRouterManager.class)));
@@ -99,6 +115,92 @@ public class ZoneManagerUnitTest {
     }
 
     @Test
+    public void itGetsCorrectNSECRecordFromStaticAndDynamicZones() throws 
Exception {
+
+        final Name qname = Name.fromString("dns1.example.com.");
+        final InetAddress client = InetAddress.getByName("192.168.56.78");
+
+        DNSAccessRecord.Builder builder = new DNSAccessRecord.Builder(1L, 
client);
+        builder = spy(builder);
+
+        Name m_an, m_host, m_admin;
+        m_an = Name.fromString("dns1.example.com.");
+        m_host = Name.fromString("dns1.example.com.");
+        m_admin = Name.fromString("admin.example.com.");
+        Record ar;
+        NSRecord ns;
+        NSECRecord nsec;
+        ar = new SOARecord(m_an, DClass.IN, 0x13A8,
+                m_host, m_admin, 0xABCDEF12L, 0xCDEF1234L,
+                0xEF123456L, 0x12345678L, 0x3456789AL);
+
+        ns = new NSRecord(m_an, DClass.IN, 12345L, m_an);
+        nsec = new NSECRecord(m_an, DClass.IN, 12345L, new 
Name("foobar.dns1.example.com."), new int[]{1});
+        Record[] records = new Record[] {ar, ns, nsec};
+        m_an = Name.fromString("dns1.example.com.");
+        Zone zone = new Zone(m_an, records);
+        // static zone
+        doReturn(zone).when(zoneManager).getZone(qname, Type.NSEC);
+
+        DNSRouteResult dnsRouteResult = new DNSRouteResult();
+        ObjectNode node = JsonNodeFactory.instance.objectNode();
+        ArrayNode domainNode = node.putArray("domains");
+        domainNode.add("example.com");
+        node.put("routingName","edge");
+        node.put("coverageZoneOnly", false);
+        DeliveryService ds1 = new DeliveryService("ds1", node);
+
+
+        dnsRouteResult.setDeliveryService(ds1);
+        InetRecord address = new InetRecord("cdn-tr.dns1.example.com.", 
12345L);
+        List<InetRecord> list = new ArrayList<>();
+        list.add(address);
+        dnsRouteResult.setAddresses(list);
+
+        Record cnameRecord = new CNAMERecord(new Name("dns1.example.com."), 
DClass.IN, 12345L, new Name("cdn-tr.dns1.example.com."));
+        Record nsecRecord = new NSECRecord(new Name("edge.dns1.example.com."), 
DClass.IN, 12345L, new Name("foobar.dns1.example.com."), new int[]{1});
+
+        // Add records for dynamic zones
+        Record[] recordArray = new Record[]{cnameRecord, ar, nsecRecord, ns};
+        List<Record> recordList = Arrays.asList(recordArray);
+        Zone dynamicZone = new Zone(new Name("dns1.example.com."), 
recordArray);
+
+        CacheLoader<ZoneKey, Zone> loader;
+        loader = new CacheLoader<>() {
+            @Override
+            public Zone load(ZoneKey zoneKey) {
+                return dynamicZone;
+            }
+
+        };
+        loader.load(new ZoneKey(Name.fromString("dns1.example.com."), 
Arrays.asList(records)));
+        LoadingCache<ZoneKey, Zone> dynamicZoneCache = 
CacheBuilder.newBuilder().build(loader);
+
+        // stub calls for signatureManager, dynamicZoneCache and 
generateDynamicZoneKey
+        when(ZoneManager.getDynamicZoneCache()).thenReturn(dynamicZoneCache);
+        ZoneKey zk = new ZoneKey(Name.fromString("dns1.example.com."), 
recordList);
+        dynamicZoneCache.put(zk, dynamicZone);
+
+        when(ZoneManager.getSignatureManager()).thenReturn(signatureManager);
+        Answer<ZoneKey> currentTimeAnswer = invocation -> zk;
+
+        when(ZoneManager.getSignatureManager().generateDynamicZoneKey(
+                eq(Name.fromString("dns1.example.com.")),
+                anyList(),
+                eq(true))).
+                then(currentTimeAnswer);
+        when(trafficRouter.isEdgeDNSRouting()).thenReturn(true);
+        when(trafficRouter.route(any(DNSRequest.class), 
any(StatTracker.Track.class))).thenReturn(dnsRouteResult);
+        Zone resultZone = zoneManager.getZone(qname, Type.NSEC, client, true, 
builder);
+        // make sure the function gets called with the correct records as 
expected
+        verify(ZoneManager.getSignatureManager()).generateDynamicZoneKey( 
eq(Name.fromString("dns1.example.com.")),
+                argThat(t -> t.containsAll(Arrays.asList(nsecRecord, ns, ar))),
+                eq(true));
+        SetResponse setResponse = resultZone.findRecords(new 
Name(ds1.getRoutingName() + "." + "dns1.example.com."), Type.NSEC);
+        assertThat(setResponse.isNXDOMAIN(), equalTo(false));
+    }
+
+    @Test
     public void testZonesAreEqual() throws java.net.UnknownHostException, 
org.xbill.DNS.TextParseException {
         class TestCase {
             String reason;

Reply via email to