Skip to content

Commit

Permalink
Stop NetworkAddressRules doing DNS lookups
Browse files Browse the repository at this point in the history
By distinguishing between DomainNameWildcard rules and IP based rules
  • Loading branch information
Mahoney committed Sep 5, 2023
1 parent aa29d9c commit 20adc25
Show file tree
Hide file tree
Showing 3 changed files with 314 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public int hashCode() {
}
}

private static class DomainNameWildcard extends NetworkAddressRange {
static class DomainNameWildcard extends NetworkAddressRange {

private final Pattern namePattern;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@

import static com.github.tomakehurst.wiremock.common.NetworkAddressRange.ALL;
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.toSet;

import com.google.common.collect.ImmutableSet;
import com.google.common.net.InetAddresses;
import java.util.Set;

public class NetworkAddressRules {
Expand All @@ -28,19 +30,62 @@ public static Builder builder() {
}

private final Set<NetworkAddressRange> allowed;
private final Set<NetworkAddressRange> allowedHostPatterns;
private final Set<NetworkAddressRange> denied;
private final Set<NetworkAddressRange> deniedHostPatterns;

public static NetworkAddressRules ALLOW_ALL =
new NetworkAddressRules(ImmutableSet.of(ALL), emptySet());

public NetworkAddressRules(Set<NetworkAddressRange> allowed, Set<NetworkAddressRange> denied) {
this.allowed = allowed;
this.denied = denied;
this.allowed =
defaultIfEmpty(
allowed.stream()
.filter(
networkAddressRange ->
!(networkAddressRange instanceof NetworkAddressRange.DomainNameWildcard))
.collect(toSet()),
ImmutableSet.of(ALL));
this.allowedHostPatterns =
defaultIfEmpty(
allowed.stream()
.filter(
networkAddressRange ->
(networkAddressRange instanceof NetworkAddressRange.DomainNameWildcard))
.collect(toSet()),
ImmutableSet.of(ALL));
this.denied =
denied.stream()
.filter(
networkAddressRange ->
!(networkAddressRange instanceof NetworkAddressRange.DomainNameWildcard))
.collect(toSet());
this.deniedHostPatterns =
denied.stream()
.filter(
networkAddressRange ->
(networkAddressRange instanceof NetworkAddressRange.DomainNameWildcard))
.map(
networkAddressRange -> (NetworkAddressRange.DomainNameWildcard) networkAddressRange)
.collect(toSet());
}

private static <T> Set<T> defaultIfEmpty(Set<T> original, Set<T> ifEmpty) {
if (original.isEmpty()) {
return ifEmpty;
} else {
return original;
}
}

public boolean isAllowed(String testValue) {
return allowed.stream().anyMatch(rule -> rule.isIncluded(testValue))
&& denied.stream().noneMatch(rule -> rule.isIncluded(testValue));
if (InetAddresses.isInetAddress(testValue)) {
return allowed.stream().anyMatch(rule -> rule.isIncluded(testValue))
&& denied.stream().noneMatch(rule -> rule.isIncluded(testValue));
} else {
return allowedHostPatterns.stream().anyMatch(rule -> rule.isIncluded(testValue))
&& deniedHostPatterns.stream().noneMatch(rule -> rule.isIncluded(testValue));
}
}

public static class Builder {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
/*
* Copyright (C) 2023 Thomas Akehurst
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.tomakehurst.wiremock.http;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.github.tomakehurst.wiremock.common.NetworkAddressRules;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.stream.Stream;
import org.apache.hc.client5.http.impl.InMemoryDnsResolver;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class NetworkAddressRulesAdheringDnsResolverTest {

InMemoryDnsResolver dns = new InMemoryDnsResolver();

@ParameterizedTest
@ValueSource(strings = {"10.1.1.2", "2.example.com"})
void resolveReturnsWithUnmatchedIpv4DenyRule(String host) throws UnknownHostException {
register("1.example.com", "10.1.1.1");
register("2.example.com", "10.1.1.2");

NetworkAddressRules rules = NetworkAddressRules.builder().deny("10.1.1.1").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThat(resolver.resolve(host)).isEqualTo(dns.resolve(host));
}

@ParameterizedTest
@ValueSource(
strings = {
"10.1.1.1",
"1.example.com",
"3.example.com",
})
void resolveThrowsExceptionWithMatchedIpv4DenyRule(String host) throws UnknownHostException {
register("1.example.com", "10.1.1.1");
register("2.example.com", "10.1.1.2");

NetworkAddressRules rules = NetworkAddressRules.builder().deny("10.1.1.1").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThatThrownBy(() -> resolver.resolve(host));
}

@ParameterizedTest
@ValueSource(strings = {"10.1.1.2", "10.1.1.3", "2.example.com"})
void resolveReturnsForHostnameResolvingToMultipleAddressesWithUnmatchedIpv4DenyRule(String host)
throws UnknownHostException {
register("1.example.com", "10.1.1.0", "10.1.1.1");
register("2.example.com", "10.1.1.2", "10.1.1.3");

NetworkAddressRules rules = NetworkAddressRules.builder().deny("10.1.1.1").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThat(resolver.resolve(host)).isEqualTo(dns.resolve(host));
}

@ParameterizedTest
@ValueSource(strings = {"10.1.1.1", "1.example.com"})
void resolveThrowsExceptionForHostnameResolvingToMultipleAddressesWithMatchedIpv4DenyRule(
String host) throws UnknownHostException {
register("1.example.com", "10.1.1.0", "10.1.1.1");
register("2.example.com", "10.1.1.2", "10.1.1.3");

NetworkAddressRules rules = NetworkAddressRules.builder().deny("10.1.1.1").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThatThrownBy(() -> resolver.resolve(host));
}

@ParameterizedTest
@ValueSource(strings = {"10.1.1.1", "1.example.com"})
void resolveReturnsWithUnmatchedIpv4AllowRule(String host) throws UnknownHostException {
register("1.example.com", "10.1.1.1");
register("2.example.com", "10.1.1.2");

NetworkAddressRules rules = NetworkAddressRules.builder().allow("10.1.1.1").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThat(resolver.resolve(host)).isEqualTo(dns.resolve(host));
}

@ParameterizedTest
@ValueSource(
strings = {
"10.1.1.2",
"2.example.com",
"3.example.com",
})
void resolveThrowsExceptionWithMatchedIpv4AllowRule(String host) throws UnknownHostException {
register("1.example.com", "10.1.1.1");
register("2.example.com", "10.1.1.2");

NetworkAddressRules rules = NetworkAddressRules.builder().allow("10.1.1.1").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThatThrownBy(() -> resolver.resolve(host));
}

@ParameterizedTest
@ValueSource(
strings = {
"10.1.1.1",
})
void resolveReturnsForHostnameResolvingToMultipleAddressesWithUnmatchedIpv4AllowRule(String host)
throws UnknownHostException {
register("1.example.com", "10.1.1.0", "10.1.1.1");
register("2.example.com", "10.1.1.2", "10.1.1.3");

NetworkAddressRules rules = NetworkAddressRules.builder().allow("10.1.1.1").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThat(resolver.resolve(host)).isEqualTo(dns.resolve(host));
}

@ParameterizedTest
@ValueSource(
strings = {
"10.1.1.0",
"10.1.1.2",
"10.1.1.3",
"1.example.com",
"2.example.com",
"3.example.com",
})
void resolveThrowsExceptionForHostnameResolvingToMultipleAddressesWithMatchedIpv4AllowRule(
String host) throws UnknownHostException {
register("1.example.com", "10.1.1.0", "10.1.1.1");
register("2.example.com", "10.1.1.2", "10.1.1.3");

NetworkAddressRules rules = NetworkAddressRules.builder().allow("10.1.1.1").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThatThrownBy(() -> resolver.resolve(host));
}

@ParameterizedTest
@ValueSource(
strings = {
"10.1.1.1",
"10.1.1.2",
"2.example.com",
})
void resolveReturnsForIpv4AddressWithHostnameDenyRule(String host) throws UnknownHostException {
register("1.example.com", "10.1.1.1");
register("2.example.com", "10.1.1.2");

NetworkAddressRules rules = NetworkAddressRules.builder().deny("1.example.com").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThat(resolver.resolve(host)).isEqualTo(dns.resolve(host));
}

@ParameterizedTest
@ValueSource(
strings = {
"1.example.com",
"3.example.com",
})
void resolveThrowsExceptionForIpv4AddressWithHostnameDenyRule(String host)
throws UnknownHostException {
register("1.example.com", "10.1.1.1");
register("2.example.com", "10.1.1.2");

NetworkAddressRules rules = NetworkAddressRules.builder().deny("1.example.com").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThatThrownBy(() -> resolver.resolve(host));
}

@ParameterizedTest
@ValueSource(
strings = {
"10.1.1.1",
"10.1.1.2",
"1.example.com",
})
void resolveReturnsForIpv4AddressWithHostnameAllowRule(String host) throws UnknownHostException {
register("1.example.com", "10.1.1.1");
register("2.example.com", "10.1.1.2");

NetworkAddressRules rules = NetworkAddressRules.builder().allow("1.example.com").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThat(resolver.resolve(host)).isEqualTo(dns.resolve(host));
}

@ParameterizedTest
@ValueSource(
strings = {
"2.example.com",
"3.example.com",
})
void resolveThrowsExceptionForIpv4AddressWithHostnameAllowRule(String host)
throws UnknownHostException {
register("1.example.com", "10.1.1.1");
register("2.example.com", "10.1.1.2");

NetworkAddressRules rules = NetworkAddressRules.builder().allow("1.example.com").build();

NetworkAddressRulesAdheringDnsResolver resolver =
new NetworkAddressRulesAdheringDnsResolver(dns, rules);

assertThatThrownBy(() -> resolver.resolve(host));
}

private void register(String host, String... ipAddresses) throws UnknownHostException {
dns.add(
host,
Stream.of(ipAddresses)
.map(NetworkAddressRulesAdheringDnsResolverTest::toInetAddress)
.toArray(InetAddress[]::new));
for (String ipAddress : ipAddresses) {
dns.add(ipAddress, InetAddress.getByName(ipAddress));
}
}

private static InetAddress toInetAddress(String ipAddress) {
try {
return InetAddress.getByName(ipAddress);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
}

0 comments on commit 20adc25

Please sign in to comment.