Skip to content

Commit

Permalink
wttech#29: Refactored SlingReferrerFilterTest to remove NPE when Filt…
Browse files Browse the repository at this point in the history
…er is not configured.

wttech#29
  • Loading branch information
Bartosz Wesolowski committed Mar 1, 2019
1 parent 5bc5eb3 commit e8b1e22
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 28 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ target
.project
.settings
.idea/
/*.iml
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,23 @@
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;
import org.apache.http.impl.auth.BasicScheme;
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.
Expand All @@ -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<String, ArrayList<String>> hostsMap = GSON
.fromJson(hostsString, Map.class);
String regexpString = StringUtils
.substringBetween(body, "\"allow.hosts.regexp\":", ",\"filter.methods\"");
@SuppressWarnings("unchecked") Map<String, ArrayList<String>> regexpMap = GSON
.fromJson(regexpString, Map.class);
List<String> hosts = hostsMap.get("values");
List<String> 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<ReferrerFilterConfigModel> configModel = GSON.fromJson(body, new TypeToken<List<ReferrerFilterConfigModel>>(){}.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<String> getAllowedHosts() {
List<String> allowedHosts = properties.allowedHosts.getValues();
return filterBlank(allowedHosts);
}

public List<String> getAllowedHostsRegeps() {
List<String> allowedHosts = properties.allowedHostsRegexps.getValues();
return filterBlank(allowedHosts);
}

private List<String> filterBlank(List<String> 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<String> values;

public List<String> getValues() {
return Optional.ofNullable(values)
.orElse(Collections.emptyList());
}
}
}

0 comments on commit e8b1e22

Please sign in to comment.