use of org.opencastproject.security.urlsigning.exception.UrlSigningException in project opencast by opencast.
the class ToolsEndpoint method getVideoEditor.
@GET
@Path("{mediapackageid}/editor.json")
@Produces(MediaType.APPLICATION_JSON)
@RestQuery(name = "getVideoEditor", description = "Returns all the information required to get the editor tool started", returnDescription = "JSON object", pathParameters = { @RestParameter(name = "mediapackageid", description = "The id of the media package", isRequired = true, type = RestParameter.Type.STRING) }, reponses = { @RestResponse(description = "Media package found", responseCode = SC_OK), @RestResponse(description = "Media package not found", responseCode = SC_NOT_FOUND) })
public Response getVideoEditor(@PathParam("mediapackageid") final String mediaPackageId) throws IndexServiceException, NotFoundException {
if (!isEditorAvailable(mediaPackageId))
return R.notFound();
// Select tracks
final Event event = getEvent(mediaPackageId).get();
final MediaPackage mp = index.getEventMediapackage(event);
List<MediaPackageElement> previewPublications = getPreviewElementsFromPublication(getInternalPublication(mp));
// Collect previews and tracks
List<JValue> jPreviews = new ArrayList<>();
List<JValue> jTracks = new ArrayList<>();
for (MediaPackageElement element : previewPublications) {
final URI elementUri;
if (urlSigningService.accepts(element.getURI().toString())) {
try {
String clientIP = null;
if (signWithClientIP) {
clientIP = securityService.getUserIP();
}
elementUri = new URI(urlSigningService.sign(element.getURI().toString(), expireSeconds, null, clientIP));
} catch (URISyntaxException e) {
logger.error("Error while trying to sign the preview urls because: {}", getStackTrace(e));
throw new WebApplicationException(e, SC_INTERNAL_SERVER_ERROR);
} catch (UrlSigningException e) {
logger.error("Error while trying to sign the preview urls because: {}", getStackTrace(e));
throw new WebApplicationException(e, SC_INTERNAL_SERVER_ERROR);
}
} else {
elementUri = element.getURI();
}
jPreviews.add(obj(f("uri", v(elementUri.toString())), f("flavor", v(element.getFlavor().getType()))));
if (!Type.Track.equals(element.getElementType()))
continue;
JObject jTrack = obj(f("id", v(element.getIdentifier())), f("flavor", v(element.getFlavor().getType())));
// Check if there's a waveform for the current track
Opt<Attachment> optWaveform = getWaveformForTrack(mp, element);
if (optWaveform.isSome()) {
final URI waveformUri;
if (urlSigningService.accepts(element.getURI().toString())) {
try {
waveformUri = new URI(urlSigningService.sign(optWaveform.get().getURI().toString(), expireSeconds, null, null));
} catch (URISyntaxException e) {
logger.error("Error while trying to serialize the waveform urls because: {}", getStackTrace(e));
throw new WebApplicationException(e, SC_INTERNAL_SERVER_ERROR);
} catch (UrlSigningException e) {
logger.error("Error while trying to sign the preview urls because: {}", getStackTrace(e));
throw new WebApplicationException(e, SC_INTERNAL_SERVER_ERROR);
}
} else {
waveformUri = optWaveform.get().getURI();
}
jTracks.add(jTrack.merge(obj(f("waveform", v(waveformUri.toString())))));
} else {
jTracks.add(jTrack);
}
}
// Get existing segments
List<JValue> jSegments = new ArrayList<>();
for (Tuple<Long, Long> segment : getSegments(mp)) {
jSegments.add(obj(f(START_KEY, v(segment.getA())), f(END_KEY, v(segment.getB()))));
}
// Get workflows
List<JValue> jWorkflows = new ArrayList<>();
for (WorkflowDefinition workflow : getEditingWorkflows()) {
jWorkflows.add(obj(f("id", v(workflow.getId())), f("name", v(workflow.getTitle(), Jsons.BLANK))));
}
return RestUtils.okJson(obj(f("title", v(mp.getTitle(), Jsons.BLANK)), f("date", v(event.getRecordingStartDate(), Jsons.BLANK)), f("series", obj(f("id", v(event.getSeriesId(), Jsons.BLANK)), f("title", v(event.getSeriesName(), Jsons.BLANK)))), f("presenters", arr($(event.getPresenters()).map(Functions.stringToJValue))), f("previews", arr(jPreviews)), f(TRACKS_KEY, arr(jTracks)), f("duration", v(mp.getDuration())), f(SEGMENTS_KEY, arr(jSegments)), f("workflows", arr(jWorkflows))));
}
use of org.opencastproject.security.urlsigning.exception.UrlSigningException in project opencast by opencast.
the class GenericUrlSigningProviderTest method testMultitenantSign.
@Test
public void testMultitenantSign() throws UrlSigningException, ConfigurationException {
properties.put(GenericUrlSigningProvider.ID_PREFIX + ".1", KEY_ID);
properties.put(GenericUrlSigningProvider.URL_PREFIX + ".1", MATCHING_URI);
properties.put(GenericUrlSigningProvider.KEY_PREFIX + ".1", KEY);
properties.put(GenericUrlSigningProvider.ID_PREFIX + ".2", ORGANIZATION_A_KEY_ID);
properties.put(GenericUrlSigningProvider.URL_PREFIX + ".2", ORGANIZATION_A_MATCHING_URI);
properties.put(GenericUrlSigningProvider.KEY_PREFIX + ".2", ORGANIZATION_A_KEY);
properties.put(GenericUrlSigningProvider.ORGANIZATION_PREFIX + ".2", ORGANIZATION_A_ID);
properties.put(GenericUrlSigningProvider.ID_PREFIX + ".3", ORGANIZATION_B_KEY_ID);
properties.put(GenericUrlSigningProvider.URL_PREFIX + ".3", ORGANIZATION_B_MATCHING_URI);
properties.put(GenericUrlSigningProvider.KEY_PREFIX + ".3", ORGANIZATION_B_KEY);
properties.put(GenericUrlSigningProvider.ORGANIZATION_PREFIX + ".3", ORGANIZATION_B_ID);
signerA.updated(properties);
signerB.updated(properties);
DateTime before = new DateTime(2020, 03, 01, 00, 46, 17, 0, DateTimeZone.UTC);
Policy policy;
String result;
boolean exceptionThrown;
// Organization A can sign its URLs using its key
policy = Policy.mkSimplePolicy(ORGANIZATION_A_RESOURCE_PATH, before);
result = signerA.sign(policy);
logger.info(result);
assertEquals("http://organization-a.opencast.org/path/to/resource.mp4?policy=eyJTdGF0ZW1lbnQiOnsiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6MTU4MzAyMzU3NzAwMH0sIlJlc291cmNlIjoiaHR0cDpcL1wvb3JnYW5pemF0aW9uLWEub3BlbmNhc3Qub3JnXC9wYXRoXC90b1wvcmVzb3VyY2UubXA0In19&keyId=key-id-organization-a&signature=ea715d6ff561f49bb6e2cb8cc3e925029e139f14eeda62fc92573f362c694423", result);
// Organization A can sign URLs not specific to any organization
policy = Policy.mkSimplePolicy(RESOURCE_PATH, before);
result = signerA.sign(policy);
logger.info(result);
assertEquals("http://www.opencast.org/path/to/resource.mp4?policy=eyJTdGF0ZW1lbnQiOnsiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6MTU4MzAyMzU3NzAwMH0sIlJlc291cmNlIjoiaHR0cDpcL1wvd3d3Lm9wZW5jYXN0Lm9yZ1wvcGF0aFwvdG9cL3Jlc291cmNlLm1wNCJ9fQ&keyId=theId&signature=5b45e678275e6bc7b06a579f7f42e9a7ea5c58f1da130701db532f121e363e98", result);
// Organization A cannot sign URLs of organization B
exceptionThrown = false;
policy = Policy.mkSimplePolicy(ORGANIZATION_B_RESOURCE_PATH, before);
try {
result = signerA.sign(policy);
} catch (UrlSigningException e) {
exceptionThrown = true;
}
assertTrue(exceptionThrown);
// Organization B can sign its URLs using its key
policy = Policy.mkSimplePolicy(ORGANIZATION_B_RESOURCE_PATH, before);
result = signerB.sign(policy);
logger.info(result);
assertEquals("http://organization-b.opencast.org/path/to/resource.mp4?policy=eyJTdGF0ZW1lbnQiOnsiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6MTU4MzAyMzU3NzAwMH0sIlJlc291cmNlIjoiaHR0cDpcL1wvb3JnYW5pemF0aW9uLWIub3BlbmNhc3Qub3JnXC9wYXRoXC90b1wvcmVzb3VyY2UubXA0In19&keyId=key-id-organizatino-b&signature=a6d803d4766f808bf2eaabdcf2e9114f85513d3d5596b4a01cb8d2488de816e8", result);
// Organization B can sign URLs not specific to any organization
policy = Policy.mkSimplePolicy(RESOURCE_PATH, before);
result = signerB.sign(policy);
logger.info(result);
assertEquals("http://www.opencast.org/path/to/resource.mp4?policy=eyJTdGF0ZW1lbnQiOnsiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6MTU4MzAyMzU3NzAwMH0sIlJlc291cmNlIjoiaHR0cDpcL1wvd3d3Lm9wZW5jYXN0Lm9yZ1wvcGF0aFwvdG9cL3Jlc291cmNlLm1wNCJ9fQ&keyId=theId&signature=5b45e678275e6bc7b06a579f7f42e9a7ea5c58f1da130701db532f121e363e98", result);
// Organization B cannot sign URLs of organization B
exceptionThrown = false;
policy = Policy.mkSimplePolicy(ORGANIZATION_A_RESOURCE_PATH, before);
try {
result = signerB.sign(policy);
} catch (UrlSigningException e) {
exceptionThrown = true;
}
assertTrue(exceptionThrown);
}
use of org.opencastproject.security.urlsigning.exception.UrlSigningException in project opencast by opencast.
the class TrustedHttpClientImpl method getSignedUrl.
/**
* If the request is a GET, sign the URL and return a new {@link HttpUriRequest} that is signed.
*
* @param httpUriRequest
* The possible URI to sign.
* @return HttpUriRequest if the request is a GET and is configured to be signed.
* @throws TrustedHttpClientException
* Thrown if there is a problem signing the URL.
*/
protected Opt<HttpUriRequest> getSignedUrl(HttpUriRequest httpUriRequest) throws TrustedHttpClientException {
if (("GET".equalsIgnoreCase(httpUriRequest.getMethod()) || "HEAD".equalsIgnoreCase(httpUriRequest.getMethod())) && ResourceRequestUtil.isNotSigned(httpUriRequest.getURI()) && urlSigningService.accepts(httpUriRequest.getURI().toString())) {
logger.trace("Signing request with method: {} and URI: {}", httpUriRequest.getMethod(), httpUriRequest.getURI().toString());
try {
String signedUrl = urlSigningService.sign(httpUriRequest.getURI().toString(), signedUrlExpiresDuration, null, null);
HttpRequestBase signedRequest;
if ("GET".equalsIgnoreCase(httpUriRequest.getMethod())) {
signedRequest = new HttpGet(signedUrl);
} else {
signedRequest = new HttpHead(signedUrl);
}
signedRequest.setProtocolVersion(httpUriRequest.getProtocolVersion());
for (Header header : httpUriRequest.getAllHeaders()) {
signedRequest.addHeader(header);
}
return Opt.some((HttpUriRequest) signedRequest);
} catch (UrlSigningException e) {
throw new TrustedHttpClientException(e);
}
} else {
logger.trace("Not signing request with method: {} and URI: {}", httpUriRequest.getMethod(), httpUriRequest.getURI().toString());
return Opt.none();
}
}
use of org.opencastproject.security.urlsigning.exception.UrlSigningException in project opencast by opencast.
the class AbstractUrlSigningProvider method sign.
@Override
public String sign(Policy policy) throws UrlSigningException {
if (!accepts(policy.getBaseUrl())) {
throw UrlSigningException.urlNotSupported();
}
// Get the key that matches this URI since there must be one that matches as the base url has been accepted.
KeyEntry keyEntry = getKeyEntry(policy.getBaseUrl());
policy.setResourceStrategy(getResourceStrategy());
try {
URI uri = new URI(policy.getBaseUrl());
List<NameValuePair> queryStringParameters = new ArrayList<>();
if (uri.getQuery() != null) {
queryStringParameters = URLEncodedUtils.parse(new URI(policy.getBaseUrl()).getQuery(), StandardCharsets.UTF_8);
}
queryStringParameters.addAll(URLEncodedUtils.parse(ResourceRequestUtil.policyToResourceRequestQueryString(policy, keyEntry.getId(), keyEntry.getKey()), StandardCharsets.UTF_8));
return new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), uri.getPath(), URLEncodedUtils.format(queryStringParameters, StandardCharsets.UTF_8), null).toString();
} catch (Exception e) {
getLogger().error("Unable to create signed URL because {}", ExceptionUtils.getStackTrace(e));
throw new UrlSigningException(e);
}
}
use of org.opencastproject.security.urlsigning.exception.UrlSigningException in project opencast by opencast.
the class UrlSigningFilter method doFilter.
/**
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
* javax.servlet.FilterChain)
*/
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (!enabled) {
chain.doFilter(request, response);
return;
}
if (urlRegularExpressions.size() == 0) {
logger.debug("There are no regular expressions configured to protect endpoints, skipping filter.");
chain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (!("GET".equalsIgnoreCase(httpRequest.getMethod()) || "HEAD".equalsIgnoreCase(httpRequest.getMethod()))) {
logger.debug("The request '{}' is not a GET or HEAD request so skipping the filter.", httpRequest.getRequestURL());
chain.doFilter(request, response);
return;
}
boolean matches = false;
for (String urlRegularExpression : urlRegularExpressions) {
Pattern p = Pattern.compile(urlRegularExpression);
Matcher m = p.matcher(httpRequest.getRequestURL());
if (m.matches()) {
matches = true;
break;
}
}
if (!matches) {
logger.debug("The request '{}' doesn't match any of the configured regular expressions so skipping the filter.", httpRequest.getRequestURL());
chain.doFilter(request, response);
return;
}
ResourceRequest resourceRequest;
try {
resourceRequest = urlSigningVerifier.verify(httpRequest.getQueryString(), httpRequest.getRemoteAddr(), httpRequest.getRequestURL().toString(), strict);
if (resourceRequest == null) {
logger.error("Unable to process httpRequest '{}' because we got a null object as the verification.", httpRequest.getRequestURL());
httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unable to process http request because we got a null object as the verification.");
return;
}
switch(resourceRequest.getStatus()) {
case Ok:
logger.trace("The request '{}' matched a regular expression path and was accepted as a properly signed url.", httpRequest.getRequestURL());
chain.doFilter(httpRequest, response);
return;
case BadRequest:
logger.debug("Unable to process httpRequest '{}' because it was rejected as a Bad Request, usually a problem with query string: {}", httpRequest.getRequestURL(), resourceRequest.getRejectionReason());
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
case Forbidden:
logger.debug("Unable to process httpRequest '{}' because is was rejected as Forbidden, usually a problem with making policy matching the signature: {}", httpRequest.getRequestURL(), resourceRequest.getRejectionReason());
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
case Gone:
logger.debug("Unable to process httpRequest '{}' because is was rejected as Gone: {}", httpRequest.getRequestURL(), resourceRequest.getRejectionReason());
httpResponse.sendError(HttpServletResponse.SC_GONE);
return;
default:
logger.error("Unable to process httpRequest '{}' because is was rejected as status {} which is not a status we should be handling here. This must be due to a code change and is a bug.: {}", httpRequest.getRequestURL(), resourceRequest.getStatus(), resourceRequest.getRejectionReason());
httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
} catch (UrlSigningException e) {
logger.error("Unable to verify request for '{}' with query string '{}' from host '{}' because: {}", httpRequest.getRequestURL(), httpRequest.getQueryString(), httpRequest.getRemoteAddr(), ExceptionUtils.getStackTrace(e));
httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, String.format("%s is unable to verify request for '%s' with query string '%s' from host '%s' because: %s", getName(), httpRequest.getRequestURL(), httpRequest.getQueryString(), httpRequest.getRemoteAddr(), ExceptionUtils.getStackTrace(e)));
return;
}
}
Aggregations