/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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 org.opencastproject.security.urlsigning.filter;
import org.opencastproject.security.urlsigning.exception.UrlSigningException;
import org.opencastproject.security.urlsigning.verifier.UrlSigningVerifier;
import org.opencastproject.security.urlsigning.verifier.impl.UrlSigningVerifierImpl;
import org.opencastproject.urlsigning.common.Policy;
import org.opencastproject.urlsigning.common.ResourceRequest;
import org.opencastproject.urlsigning.common.ResourceRequest.Status;
import org.opencastproject.urlsigning.utils.ResourceRequestUtil;
import org.apache.commons.io.IOUtils;
import org.easymock.EasyMock;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import org.osgi.service.cm.ConfigurationException;
import java.io.IOException;
import java.util.Properties;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UrlSigningFilterTest {
private static final String BASE_URL = "http://test.com";
private Properties matchAllProperties;
private String keyId = "TheKeyID";
private String key = "TheFullKey";
private String clientIp = "10.0.0.1";
@Before
public void setUp() {
matchAllProperties = new Properties();
matchAllProperties.put(UrlSigningFilter.URL_REGEX_PREFIX + ".1", ".*");
}
@Test
public void testSkippedIfNotGetOrHead() throws ConfigurationException, IOException, ServletException {
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getMethod()).andStubReturn("POST");
EasyMock.expect(request.getRequestURL()).andStubReturn(new StringBuffer(BASE_URL + "/post/path"));
HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
FilterChain filterChain = EasyMock.createMock(FilterChain.class);
filterChain.doFilter(request, response);
EasyMock.expectLastCall();
EasyMock.replay(filterChain, request, response);
UrlSigningFilter filter = new UrlSigningFilter();
filter.updated(matchAllProperties);
filter.doFilter(request, response, filterChain);
EasyMock.verify(filterChain);
}
private HttpServletRequest createSignedHttpServletRequest(String method, String path) throws Exception {
String fullUrl = BASE_URL + path;
Policy policy = Policy.mkSimplePolicy(fullUrl, new DateTime(2056, 05, 13, 14, 32));
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getMethod()).andStubReturn(method);
EasyMock.expect(request.getRequestURL()).andStubReturn(new StringBuffer(fullUrl));
EasyMock.expect(request.getQueryString()).andStubReturn(ResourceRequestUtil.policyToResourceRequestQueryString(policy, keyId, key));
EasyMock.expect(request.getRemoteAddr()).andStubReturn(clientIp);
return request;
}
private HttpServletRequest createUnSignedHttpServletRequest(String method, String path) throws Exception {
String fullUrl = BASE_URL + path;
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getMethod()).andStubReturn(method);
EasyMock.expect(request.getRequestURL()).andStubReturn(new StringBuffer(fullUrl));
EasyMock.expect(request.getQueryString()).andStubReturn("");
EasyMock.expect(request.getRemoteAddr()).andStubReturn(clientIp);
return request;
}
@Test
public void testURLMatching() throws Exception {
Properties keys = new Properties();
keys.put(UrlSigningVerifierImpl.ID_PREFIX + ".1", keyId);
keys.put(UrlSigningVerifierImpl.KEY_PREFIX + ".1", key);
UrlSigningVerifierImpl urlSigningVerifier = new UrlSigningVerifierImpl();
urlSigningVerifier.updated(keys);
Properties properties = new Properties();
properties.load(IOUtils.toInputStream(IOUtils.toString(getClass().getResource("/UrlSigningFilter.properties"))));
UrlSigningFilter filter = new UrlSigningFilter();
filter.updated(properties);
// Check /files/collection/{collectionId}/{fileName} is protected
String path = "/files/collection/collectionId/filename.mp4";
HttpServletRequest request = createSignedHttpServletRequest("GET", path);
HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
FilterChain filterChain = EasyMock.createMock(FilterChain.class);
filterChain.doFilter(request, response);
EasyMock.expectLastCall();
EasyMock.replay(filterChain, request, response);
filter.setUrlSigningVerifier(urlSigningVerifier);
filter.doFilter(request, response, filterChain);
// Check /files/collectionuri/{collectionId}/{fileName} is not protected
path = "/files/collectionuri/collectionID/filename.mp4";
request = createUnSignedHttpServletRequest("GET", path);
response = EasyMock.createMock(HttpServletResponse.class);
filterChain = EasyMock.createMock(FilterChain.class);
filterChain.doFilter(request, response);
EasyMock.expectLastCall();
EasyMock.replay(filterChain, request, response);
filter.setUrlSigningVerifier(urlSigningVerifier);
filter.doFilter(request, response, filterChain);
// Check /files/mediapackage/{mediaPackageID}/{mediaPackageElementID} is protected
path = "/files/mediapackage/mediaPackageID/mediaPackageElementID";
request = createSignedHttpServletRequest("GET", path);
response = EasyMock.createMock(HttpServletResponse.class);
filterChain = EasyMock.createMock(FilterChain.class);
filterChain.doFilter(request, response);
EasyMock.expectLastCall();
EasyMock.replay(filterChain, request, response);
filter.setUrlSigningVerifier(urlSigningVerifier);
filter.doFilter(request, response, filterChain);
// Check /files/mediapackage/{mediaPackageID}/{mediaPackageElementID}/{fileName} is protected
path = "/files/mediapackage/mediaPackageID/mediaPackageElementID/fileName";
request = createSignedHttpServletRequest("GET", path);
response = EasyMock.createMock(HttpServletResponse.class);
filterChain = EasyMock.createMock(FilterChain.class);
filterChain.doFilter(request, response);
EasyMock.expectLastCall();
EasyMock.replay(filterChain, request, response);
filter.setUrlSigningVerifier(urlSigningVerifier);
filter.doFilter(request, response, filterChain);
// Check /staticfiles/{uuid}
path = "/staticfiles/uuid";
request = createSignedHttpServletRequest("GET", path);
response = EasyMock.createMock(HttpServletResponse.class);
filterChain = EasyMock.createMock(FilterChain.class);
filterChain.doFilter(request, response);
EasyMock.expectLastCall();
EasyMock.replay(filterChain, request, response);
filter.setUrlSigningVerifier(urlSigningVerifier);
filter.doFilter(request, response, filterChain);
// Check /staticfiles/{uuid}/url is not protected
path = "/staticfiles/uuid/url";
request = createSignedHttpServletRequest("GET", path);
response = EasyMock.createMock(HttpServletResponse.class);
filterChain = EasyMock.createMock(FilterChain.class);
filterChain.doFilter(request, response);
EasyMock.expectLastCall();
EasyMock.replay(filterChain, request, response);
filter.setUrlSigningVerifier(urlSigningVerifier);
filter.doFilter(request, response, filterChain);
// Check /archive/archive/mediapackage/{mediaPackageID}/{mediaPackageElementID}/{version} is protected
path = "/archive/archive/mediapackage/mediaPackageID/mediaPackageElementID/version";
request = createSignedHttpServletRequest("GET", path);
response = EasyMock.createMock(HttpServletResponse.class);
filterChain = EasyMock.createMock(FilterChain.class);
filterChain.doFilter(request, response);
EasyMock.expectLastCall();
EasyMock.replay(filterChain, request, response);
filter.setUrlSigningVerifier(urlSigningVerifier);
filter.doFilter(request, response, filterChain);
}
@Test
public void testCorrectPolicyAndSignature() throws Exception {
String encryptionKeyId = "theKey";
String acceptedUrl = "http://accepted.com";
String acceptedKey = "ThisIsTheKey";
String acceptedIp = "10.0.0.1";
DateTime future = new DateTime(4749125399000L);
Policy policy = Policy.mkSimplePolicy(acceptedUrl, future);
String acceptedQueryString = ResourceRequestUtil.policyToResourceRequestQueryString(policy, encryptionKeyId, acceptedKey);
ResourceRequest acceptedRequest = new ResourceRequest();
acceptedRequest.setStatus(Status.Ok);
// Setup the Mock Url Signing Service
UrlSigningVerifier urlSigningVerifier = EasyMock.createMock(UrlSigningVerifier.class);
EasyMock.expect(urlSigningVerifier.verify(acceptedQueryString, acceptedIp, acceptedUrl, true)).andReturn(acceptedRequest);
EasyMock.replay(urlSigningVerifier);
UrlSigningFilter filter = new UrlSigningFilter();
filter.setUrlSigningVerifier(urlSigningVerifier);
// Setup the Mock Request
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getMethod()).andStubReturn("GET");
EasyMock.expect(request.getRequestURL()).andStubReturn(new StringBuffer(acceptedUrl));
EasyMock.expect(request.getQueryString())
.andStubReturn(acceptedQueryString);
EasyMock.expect(request.getRemoteAddr()).andStubReturn(acceptedIp);
EasyMock.replay(request);
HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
// Setup the mock filter chain.
FilterChain chain = EasyMock.createMock(FilterChain.class);
chain.doFilter(request, response);
EasyMock.expectLastCall();
EasyMock.replay(chain);
filter.doFilter(request, response, chain);
EasyMock.verify(chain);
}
@Test
public void testDeniedOnException() throws Exception {
String encryptionKeyId = "theKey";
String acceptedUrl = "http://accepted.com";
String acceptedKey = "ThisIsTheKey";
String acceptedIp = "10.0.0.1";
DateTime future = new DateTime(4749125399000L);
Policy policy = Policy.mkSimplePolicy(acceptedUrl, future);
String acceptedQueryString = ResourceRequestUtil.policyToResourceRequestQueryString(policy, encryptionKeyId, acceptedKey);
ResourceRequest acceptedRequest = new ResourceRequest();
acceptedRequest.setStatus(Status.Ok);
// Setup the Mock Url Signing Service
UrlSigningVerifier urlSigningVerifier = EasyMock.createMock(UrlSigningVerifier.class);
EasyMock.expect(urlSigningVerifier.verify(acceptedQueryString, acceptedIp, acceptedUrl, true))
.andThrow(UrlSigningException.internalProviderError());
EasyMock.replay(urlSigningVerifier);
UrlSigningFilter filter = new UrlSigningFilter();
filter.updated(matchAllProperties);
filter.setUrlSigningVerifier(urlSigningVerifier);
// Setup the Mock Request
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getMethod()).andStubReturn("GET");
EasyMock.expect(request.getRequestURL()).andStubReturn(new StringBuffer(acceptedUrl));
EasyMock.expect(request.getQueryString())
.andStubReturn(acceptedQueryString);
EasyMock.expect(request.getRemoteAddr()).andStubReturn(acceptedIp);
EasyMock.replay(request);
HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
// Setup the mock filter chain.
FilterChain chain = EasyMock.createStrictMock(FilterChain.class);
EasyMock.replay(chain);
filter.doFilter(request, response, chain);
EasyMock.verify(chain);
}
@Test
public void testDeniedOnBadRequest() throws Exception {
String encryptionKeyId = "theKey";
String acceptedUrl = "http://accepted.com";
String acceptedKey = "ThisIsTheKey";
String acceptedIp = "10.0.0.1";
DateTime future = new DateTime(4749125399000L);
Policy policy = Policy.mkSimplePolicy(acceptedUrl, future);
String acceptedQueryString = ResourceRequestUtil.policyToResourceRequestQueryString(policy, encryptionKeyId, acceptedKey);
ResourceRequest acceptedRequest = new ResourceRequest();
acceptedRequest.setStatus(Status.BadRequest);
// Setup the Mock Url Signing Service
UrlSigningVerifier urlSigningVerifier = EasyMock.createMock(UrlSigningVerifier.class);
EasyMock.expect(urlSigningVerifier.verify(acceptedQueryString, acceptedIp, acceptedUrl, true)).andReturn(acceptedRequest);
EasyMock.replay(urlSigningVerifier);
UrlSigningFilter filter = new UrlSigningFilter();
filter.updated(matchAllProperties);
filter.setUrlSigningVerifier(urlSigningVerifier);
// Setup the Mock Request
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getMethod()).andStubReturn("GET");
EasyMock.expect(request.getRequestURL()).andStubReturn(new StringBuffer(acceptedUrl));
EasyMock.expect(request.getQueryString())
.andStubReturn(acceptedQueryString);
EasyMock.expect(request.getRemoteAddr()).andStubReturn(acceptedIp);
EasyMock.replay(request);
HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
// Setup the mock filter chain.
FilterChain chain = EasyMock.createMock(FilterChain.class);
EasyMock.replay(chain);
filter.doFilter(request, response, chain);
EasyMock.verify(chain);
}
@Test
public void testDeniedOnForbidden() throws Exception {
String encryptionKeyId = "theKey";
String acceptedUrl = "http://accepted.com";
String acceptedKey = "ThisIsTheKey";
String acceptedIp = "10.0.0.1";
DateTime future = new DateTime(4749125399000L);
Policy policy = Policy.mkSimplePolicy(acceptedUrl, future);
String acceptedQueryString = ResourceRequestUtil.policyToResourceRequestQueryString(policy, encryptionKeyId, acceptedKey);
ResourceRequest acceptedRequest = new ResourceRequest();
acceptedRequest.setStatus(Status.Forbidden);
// Setup the Mock Url Signing Service
UrlSigningVerifier urlSigningVerifier = EasyMock.createMock(UrlSigningVerifier.class);
EasyMock.expect(urlSigningVerifier.verify(acceptedQueryString, acceptedIp, acceptedUrl, true)).andReturn(acceptedRequest);
EasyMock.replay(urlSigningVerifier);
UrlSigningFilter filter = new UrlSigningFilter();
filter.updated(matchAllProperties);
filter.setUrlSigningVerifier(urlSigningVerifier);
// Setup the Mock Request
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getMethod()).andStubReturn("GET");
EasyMock.expect(request.getRequestURL()).andStubReturn(new StringBuffer(acceptedUrl));
EasyMock.expect(request.getQueryString())
.andStubReturn(acceptedQueryString);
EasyMock.expect(request.getRemoteAddr()).andStubReturn(acceptedIp);
EasyMock.replay(request);
HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
// Setup the mock filter chain.
FilterChain chain = EasyMock.createMock(FilterChain.class);
EasyMock.replay(chain);
filter.doFilter(request, response, chain);
EasyMock.verify(chain);
}
@Test
public void testDeniedOnGone() throws Exception {
String encryptionKeyId = "theKey";
String acceptedUrl = "http://accepted.com";
String acceptedKey = "ThisIsTheKey";
String acceptedIp = "10.0.0.1";
DateTime future = new DateTime(4749125399000L);
Policy policy = Policy.mkSimplePolicy(acceptedUrl, future);
String acceptedQueryString = ResourceRequestUtil.policyToResourceRequestQueryString(policy, encryptionKeyId, acceptedKey);
ResourceRequest acceptedRequest = new ResourceRequest();
acceptedRequest.setStatus(Status.Gone);
// Setup the Mock Url Signing Service
UrlSigningVerifier urlSigningVerifier = EasyMock.createMock(UrlSigningVerifier.class);
EasyMock.expect(urlSigningVerifier.verify(acceptedQueryString, acceptedIp, acceptedUrl, true)).andReturn(acceptedRequest);
EasyMock.replay(urlSigningVerifier);
UrlSigningFilter filter = new UrlSigningFilter();
filter.updated(matchAllProperties);
filter.setUrlSigningVerifier(urlSigningVerifier);
// Setup the Mock Request
HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class);
EasyMock.expect(request.getMethod()).andStubReturn("GET");
EasyMock.expect(request.getRequestURL()).andStubReturn(new StringBuffer(acceptedUrl));
EasyMock.expect(request.getQueryString())
.andStubReturn(acceptedQueryString);
EasyMock.expect(request.getRemoteAddr()).andStubReturn(acceptedIp);
EasyMock.replay(request);
HttpServletResponse response = EasyMock.createMock(HttpServletResponse.class);
// Setup the mock filter chain.
FilterChain chain = EasyMock.createMock(FilterChain.class);
EasyMock.replay(chain);
filter.doFilter(request, response, chain);
EasyMock.verify(chain);
}
}