From e8b1e223b94540bff99361a5d5e68ea08341b81f Mon Sep 17 00:00:00 2001 From: Bartosz Wesolowski Date: Fri, 1 Mar 2019 12:16:41 +0100 Subject: [PATCH] #29: Refactored SlingReferrerFilterTest to remove NPE when Filter is not configured. https://github.com/Cognifide/SecureCQ/issues/29 --- .gitignore | 1 + .../tests/SlingReferrerFilterTest.java | 116 +++++++++++++----- 2 files changed, 89 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 310c07f..dfb8072 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ target .project .settings .idea/ +/*.iml diff --git a/src/main/java/com/cognifide/secureaem/tests/SlingReferrerFilterTest.java b/src/main/java/com/cognifide/secureaem/tests/SlingReferrerFilterTest.java index 23d62cd..6152488 100644 --- a/src/main/java/com/cognifide/secureaem/tests/SlingReferrerFilterTest.java +++ b/src/main/java/com/cognifide/secureaem/tests/SlingReferrerFilterTest.java @@ -7,8 +7,11 @@ import com.cognifide.secureaem.markers.AuthorTest; import com.cognifide.secureaem.markers.PublishTest; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpResponse; +import org.apache.http.auth.AuthenticationException; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpUriRequest; @@ -16,10 +19,11 @@ import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; -import java.util.ArrayList; +import java.io.IOException; import java.util.Collections; import java.util.List; -import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; /** * Check if Sling Referrer Filter is configured. @@ -30,43 +34,99 @@ public class SlingReferrerFilterTest extends AbstractTest implements AuthorTest, private static final Gson GSON = new Gson(); - private static final DefaultHttpClient client = new DefaultHttpClient(); + private static final String FILTER_URL = + "/system/console/configMgr/org.apache.sling.security.impl.ReferrerFilter.json"; + + private static final DefaultHttpClient HTTP_CLIENT = new DefaultHttpClient(); public SlingReferrerFilterTest(Configuration config) { super(config); } @Override public boolean doTest(String url, String instanceName) throws Exception { + HttpResponse response = fetchRefererConfig(url, instanceName); + if (response.getStatusLine().getStatusCode() == 200) { + String body = EntityUtils.toString(response.getEntity()); + return validateResponseBody(instanceName, body); + } else { + addErrorMessage("Cannot get Sling Referrer Filter configuration from [%s]", instanceName); + return false; + } + } + + private HttpResponse fetchRefererConfig(String url, String instanceName) throws AuthenticationException, IOException { UsernamePasswordCredentials credentials = getUsernamePasswordCredentials(instanceName); String testedUrl = - url + "/system/console/configMgr/org.apache.sling.security.impl.ReferrerFilter.json"; + url + FILTER_URL; HttpUriRequest request = new HttpGet(testedUrl); request.addHeader(new BasicScheme().authenticate(credentials, request, null)); - HttpResponse response = client.execute(request); - String body = EntityUtils.toString(response.getEntity()); - if (response.getStatusLine().getStatusCode() == 200) { - String hostsString = StringUtils - .substringBetween(body, "\"allow.hosts\":", ",\"allow.hosts.regexp\""); - @SuppressWarnings("unchecked") Map> hostsMap = GSON - .fromJson(hostsString, Map.class); - String regexpString = StringUtils - .substringBetween(body, "\"allow.hosts.regexp\":", ",\"filter.methods\""); - @SuppressWarnings("unchecked") Map> regexpMap = GSON - .fromJson(regexpString, Map.class); - List hosts = hostsMap.get("values"); - List regexps = regexpMap.get("values"); - hosts.removeAll(Collections.singletonList("")); - regexps.removeAll(Collections.singletonList("")); - if (hosts.isEmpty() && regexps.isEmpty()) { - addErrorMessage("Sling Referrer Filter is not configured on [%s]", instanceName); - return false; - } else { - addInfoMessage("Sling Referrer Filter is configured on [%s]", instanceName); - return true; - } + return HTTP_CLIENT.execute(request); + } + + private boolean validateResponseBody(String instanceName, String body) { + List configModel = GSON.fromJson(body, new TypeToken>(){}.getType()); + boolean validationResult = false; + if(!configModel.isEmpty()) { + validationResult = validateConfig(instanceName, configModel.get(0)); } else { - addErrorMessage("Cannot get Sling Referrer Filter configuration from [%s]", instanceName); - return false; + addErrorMessage("Sling Referrer Filter is not configured on [%s]", instanceName); + } + return validationResult; + } + + private boolean validateConfig(String instanceName, ReferrerFilterConfigModel configModel) { + boolean validationResult = false; + if (configModel.getAllowedHosts().isEmpty() || configModel.getAllowedHostsRegeps().isEmpty()) { + addErrorMessage("Sling Referrer Filter is not configured on [%s]", instanceName); + } else { + addInfoMessage("Sling Referrer Filter is configured on [%s]", instanceName); + validationResult = true; + } + return validationResult; + } + + private static class ReferrerFilterConfigModel { + + private ReferrerFilterConfigProperties properties; + + public List getAllowedHosts() { + List allowedHosts = properties.allowedHosts.getValues(); + return filterBlank(allowedHosts); + } + + public List getAllowedHostsRegeps() { + List allowedHosts = properties.allowedHostsRegexps.getValues(); + return filterBlank(allowedHosts); + } + + private List filterBlank(List source) { + return source.stream() + .filter(StringUtils::isNotBlank) + .collect(Collectors.toList()); + } + } + + private static class ReferrerFilterConfigProperties { + + @SerializedName("allow.hosts") + private MultipleValueConfig allowedHosts; + + @SerializedName("allow.hosts.regexp") + private MultipleValueConfig allowedHostsRegexps; + } + + private static class MultipleValueConfig { + + private String name; + + @SerializedName("is_set") + private boolean isSet; + + private List values; + + public List getValues() { + return Optional.ofNullable(values) + .orElse(Collections.emptyList()); } } }