test for handlung DNS lookup failures

This commit is contained in:
Michael Hoennig 2024-09-06 12:39:11 +02:00
parent e94f2f254a
commit bab85c5581
3 changed files with 69 additions and 20 deletions

View File

@ -4,6 +4,7 @@ import org.apache.commons.collections4.EnumerationUtils;
import javax.naming.InvalidNameException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.ServiceUnavailableException;
import javax.naming.directory.Attribute;
@ -23,7 +24,6 @@ public class Dns {
public enum Status {
SUCCESS,
RECORD_TYPE_NOT_FOUND,
NAME_NOT_FOUND,
INVALID_NAME,
SERVICE_UNAVAILABLE,
@ -31,6 +31,22 @@ public class Dns {
}
public record Result(Status status, List<String> records, NamingException exception) {
public static Result fromRecords(final NamingEnumeration<?> enumeration) {
final List<String> records = enumeration == null
? emptyList()
: EnumerationUtils.toList(enumeration).stream().map(Object::toString).toList();
return new Result(Status.SUCCESS, records, null);
}
public static Result fromException(final NamingException exception) {
return switch (exception) {
case ServiceUnavailableException exc -> new Result(Status.SERVICE_UNAVAILABLE, null, exc);
case NameNotFoundException exc -> new Result(Status.NAME_NOT_FOUND, null, exc);
case InvalidNameException exc -> new Result(Status.INVALID_NAME, null, exc);
case NamingException exc -> new Result(Status.UNKNOWN_FAILURE, null, exc);
};
}
}
private final String domainName;
@ -51,23 +67,12 @@ public class Dns {
try {
final var env = new Hashtable<>();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");
final Attribute r = new InitialDirContext(env)
final Attribute records = new InitialDirContext(env)
.getAttributes(domainName, new String[] { recordType })
.get(recordType);
return new Result(
r == null ? Status.RECORD_TYPE_NOT_FOUND : Status.SUCCESS,
r == null
? emptyList()
: EnumerationUtils.toList(r.getAll()).stream().map(Object::toString).toList(),
null);
} catch (final ServiceUnavailableException e) {
return new Result(Status.SERVICE_UNAVAILABLE, null, e);
} catch (final NameNotFoundException e) {
return new Result(Status.NAME_NOT_FOUND, null, e);
} catch (InvalidNameException e) {
return new Result(Status.INVALID_NAME, null, e);
} catch (NamingException e) {
return new Result(Status.UNKNOWN_FAILURE, null, e);
return Result.fromRecords(records != null ? records.getAll() : null);
} catch (final NamingException exception) {
return Result.fromException(exception);
}
}

View File

@ -54,12 +54,9 @@ class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator {
if (found.isPresent()) {
break;
}
case Dns.Status.RECORD_TYPE_NOT_FOUND:
violations.add("Domain " + assetEntity.getIdentifier() + " exists, but no record 'TXT Hostsharing-domain-setup-challenge:FIXME' found ");
break;
case Dns.Status.NAME_NOT_FOUND:
// no DNS verification necessary
// no DNS verification necessary / FIXME: at least if the superdomain is at registrar level
break;
case Dns.Status.INVALID_NAME:

View File

@ -9,6 +9,10 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.ValueSource;
import javax.naming.InvalidNameException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.ServiceUnavailableException;
import java.util.Map;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER;
@ -176,6 +180,49 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
assertThat(result).isEmpty();
}
enum DnsLookupFailureTestCase {
SERVICE_UNAVAILABLE(
new ServiceUnavailableException("no Internet connection"),
"DNS request for example.org failed: javax.naming.ServiceUnavailableException: no Internet connection"),
NAME_NOT_FOUND(
new NameNotFoundException("domain not registered"),
null), // no
INVALID_NAME(
new InvalidNameException("domain name too long or whatever"),
"Invalid domain name example.org"),
UNKNOWN_FAILURE(
new NamingException("some other problem"),
"DNS request for example.org failed: javax.naming.NamingException: some other problem");
public final NamingException givenException;
public final String expectedErrorMessage;
DnsLookupFailureTestCase(final NamingException givenException, final String expectedErrorMessage) {
this.givenException = givenException;
this.expectedErrorMessage = expectedErrorMessage;
}
}
@ParameterizedTest
@EnumSource(DnsLookupFailureTestCase.class)
void handlesDnsLookupFailures(final DnsLookupFailureTestCase testCase) {
// given
Dns.fakeNextResult(Dns.Result.fromException(testCase.givenException));
final var domainSetupHostingAssetEntity = validEntityBuilder().build();
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
// when
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
// then
if (testCase.expectedErrorMessage != null) {
assertThat(result).containsExactly(testCase.expectedErrorMessage);
} else {
assertThat(result).isEmpty();
}
}
private static HsHostingAssetRealEntity createValidParentDomainSetupAsset(final String parentDomainName) {
final var bookingItem = HsBookingItemRealEntity.builder()
.type(HsBookingItemType.DOMAIN_SETUP)