check-domain-setup-permission #97

Merged
hsh-michaelhoennig merged 17 commits from check-domain-setup-permission into master 2024-09-10 13:15:03 +02:00
3 changed files with 69 additions and 20 deletions
Showing only changes of commit bab85c5581 - Show all commits

View File

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

View File

@ -54,12 +54,9 @@ class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator {
if (found.isPresent()) { if (found.isPresent()) {
break; break;
hsh-michaelhoennig marked this conversation as resolved
Review

use getParentAsset == null + Test

use getParentAsset == null + Test
} }
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: 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; break;
case Dns.Status.INVALID_NAME: 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.EnumSource;
import org.junit.jupiter.params.provider.ValueSource; 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 java.util.Map;
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER;
@ -176,6 +180,49 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
assertThat(result).isEmpty(); 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) { private static HsHostingAssetRealEntity createValidParentDomainSetupAsset(final String parentDomainName) {
final var bookingItem = HsBookingItemRealEntity.builder() final var bookingItem = HsBookingItemRealEntity.builder()
.type(HsBookingItemType.DOMAIN_SETUP) .type(HsBookingItemType.DOMAIN_SETUP)