Search in sources :

Example 6 with RestMethod

use of com.github.ambry.rest.RestMethod in project ambry by linkedin.

the class AmbryUrlSigningService method getSignedUrl.

@Override
public String getSignedUrl(RestRequest restRequest) throws RestServiceException {
    Map<String, Object> args = restRequest.getArgs();
    String restMethodInSignedUrlStr = RestUtils.getHeader(args, RestUtils.Headers.URL_TYPE, true);
    RestMethod restMethodInSignedUrl;
    try {
        restMethodInSignedUrl = RestMethod.valueOf(restMethodInSignedUrlStr);
    } catch (IllegalArgumentException e) {
        throw new RestServiceException("Unrecognized RestMethod: " + restMethodInSignedUrlStr, RestServiceErrorCode.InvalidArgs);
    }
    StringBuilder urlBuilder = new StringBuilder();
    switch(restMethodInSignedUrl) {
        case GET:
            urlBuilder.append(downloadEndpoint);
            break;
        case POST:
            urlBuilder.append(uploadEndpoint);
            break;
        default:
            throw new RestServiceException("Signing request for " + restMethodInSignedUrl + " is not supported", RestServiceErrorCode.InvalidArgs);
    }
    long urlTtlSecs = defaultUrlTtlSecs;
    long maxUploadSize = defaultMaxUploadSize;
    boolean chunkUpload = false;
    Map<String, Object> argsForUrl = new HashMap<>();
    for (Map.Entry<String, Object> entry : args.entrySet()) {
        String name = entry.getKey();
        Object value = entry.getValue();
        if (name.regionMatches(true, 0, AMBRY_PARAMETERS_PREFIX, 0, AMBRY_PARAMETERS_PREFIX.length()) && value instanceof String) {
            switch(name) {
                case RestUtils.Headers.URL_TTL:
                    urlTtlSecs = Math.min(maxUrlTtlSecs, RestUtils.getLongHeader(args, RestUtils.Headers.URL_TTL, true));
                    break;
                case RestUtils.Headers.MAX_UPLOAD_SIZE:
                    maxUploadSize = RestUtils.getLongHeader(args, RestUtils.Headers.MAX_UPLOAD_SIZE, true);
                    break;
                case RestUtils.Headers.CHUNK_UPLOAD:
                    chunkUpload = RestUtils.getBooleanHeader(args, RestUtils.Headers.CHUNK_UPLOAD, true);
                    break;
                default:
                    argsForUrl.put(name, value);
                    break;
            }
        }
    }
    if (RestMethod.POST.equals(restMethodInSignedUrl)) {
        if (chunkUpload) {
            // Chunks of a stitched blob have a fixed max size to ensure that the router does not do further chunking as
            // this is not supported by the current metadata format.
            maxUploadSize = chunkUploadMaxChunkSize;
            // They also have a non-optional blob TTL to ensure that chunks that were not stitched within a reasonable time
            // span are cleaned up.
            argsForUrl.put(RestUtils.Headers.TTL, chunkUploadInitialChunkTtlSecs);
            argsForUrl.put(RestUtils.Headers.CHUNK_UPLOAD, true);
            argsForUrl.put(RestUtils.Headers.SESSION, UUID.randomUUID().toString());
        }
        argsForUrl.put(RestUtils.Headers.MAX_UPLOAD_SIZE, maxUploadSize);
    }
    argsForUrl.put(LINK_EXPIRY_TIME, time.seconds() + urlTtlSecs);
    String nextSeparator = QUERY_STRING_START;
    for (Map.Entry<String, Object> entry : argsForUrl.entrySet()) {
        String value = urlEncode(entry.getValue());
        urlBuilder.append(nextSeparator).append(entry.getKey()).append(PARAMETER_ASSIGN).append(value);
        nextSeparator = PARAMETER_SEPARATOR;
    }
    return urlBuilder.toString();
}
Also used : RestServiceException(com.github.ambry.rest.RestServiceException) HashMap(java.util.HashMap) Map(java.util.Map) HashMap(java.util.HashMap) RestMethod(com.github.ambry.rest.RestMethod)

Example 7 with RestMethod

use of com.github.ambry.rest.RestMethod in project ambry by linkedin.

the class AmbryUrlSigningService method verifySignedRequest.

@Override
public void verifySignedRequest(RestRequest restRequest) throws RestServiceException {
    if (!isRequestSigned(restRequest)) {
        throw new RestServiceException("Request is not signed - method should not have been called", RestServiceErrorCode.InternalServerError);
    }
    Map<String, Object> args = restRequest.getArgs();
    long expiryTimeSecs = RestUtils.getLongHeader(args, LINK_EXPIRY_TIME, true);
    if (time.seconds() > expiryTimeSecs) {
        throw new RestServiceException("Signed URL has expired", RestServiceErrorCode.Unauthorized);
    }
    RestMethod restMethodInUrl = RestMethod.valueOf(RestUtils.getHeader(args, RestUtils.Headers.URL_TYPE, true));
    if (!restRequest.getRestMethod().equals(restMethodInUrl)) {
        throw new RestServiceException("Type of request being made not compatible with signed URL", RestServiceErrorCode.Unauthorized);
    }
}
Also used : RestServiceException(com.github.ambry.rest.RestServiceException) RestMethod(com.github.ambry.rest.RestMethod)

Example 8 with RestMethod

use of com.github.ambry.rest.RestMethod in project ambry by linkedin.

the class GetSignedUrlHandler method handle.

/**
 * Handles a request for getting signed URLs.
 * @param restRequest the {@link RestRequest} that contains the request parameters.
 * @param restResponseChannel the {@link RestResponseChannel} where headers should be set.
 * @param callback the {@link Callback} to invoke when the response is ready (or if there is an exception).
 * @throws RestServiceException if required parameters are not found or are invalid
 */
void handle(RestRequest restRequest, RestResponseChannel restResponseChannel, Callback<ReadableStreamChannel> callback) throws RestServiceException {
    RestRequestMetrics requestMetrics = metrics.getSignedUrlMetricsGroup.getRestRequestMetrics(restRequest.isSslUsed(), false);
    restRequest.getMetricsTracker().injectMetrics(requestMetrics);
    String restMethodInSignedUrlStr = RestUtils.getHeader(restRequest.getArgs(), RestUtils.Headers.URL_TYPE, true);
    RestMethod restMethodInUrl;
    try {
        restMethodInUrl = RestMethod.valueOf(restMethodInSignedUrlStr);
    } catch (IllegalArgumentException e) {
        throw new RestServiceException("Unrecognized RestMethod: " + restMethodInSignedUrlStr, RestServiceErrorCode.InvalidArgs);
    }
    securityService.processRequest(restRequest, new SecurityProcessRequestCallback(restRequest, restMethodInUrl, restResponseChannel, callback));
}
Also used : RestServiceException(com.github.ambry.rest.RestServiceException) RestRequestMetrics(com.github.ambry.rest.RestRequestMetrics) RestMethod(com.github.ambry.rest.RestMethod)

Example 9 with RestMethod

use of com.github.ambry.rest.RestMethod in project ambry by linkedin.

the class FrontendTestUrlSigningServiceFactory method doExternalServicesBadInputTest.

/**
 * Does the tests to check for exception pipelining for exceptions returned/thrown by external services.
 * @param restMethods the {@link RestMethod} types for which the test has to be run.
 * @param expectedExceptionMsg the expected exception message.
 * @param expectRouterCall if the router should have returned a value before the exception occurs.
 * @throws JSONException
 */
private void doExternalServicesBadInputTest(RestMethod[] restMethods, String expectedExceptionMsg, boolean expectRouterCall) throws JSONException {
    for (RestMethod restMethod : restMethods) {
        if (restMethod.equals(RestMethod.UNKNOWN)) {
            continue;
        }
        JSONObject headers = new JSONObject();
        List<ByteBuffer> contents = null;
        if (restMethod.equals(RestMethod.POST)) {
            setAmbryHeadersForPut(headers, 7200, !refContainer.isCacheable(), "doExternalServicesBadInputTest", "application/octet-stream", "doExternalServicesBadInputTest", refAccount.getName(), refContainer.getName(), null);
            contents = new ArrayList<>(1);
            contents.add(null);
        }
        String blobIdStr = new BlobId(blobIdVersion, BlobId.BlobIdType.NATIVE, (byte) -1, Account.UNKNOWN_ACCOUNT_ID, Container.UNKNOWN_CONTAINER_ID, clusterMap.getAllPartitionIds(null).get(0), false, BlobId.BlobDataType.DATACHUNK).getID();
        try {
            doOperation(createRestRequest(restMethod, blobIdStr, headers, contents), new MockRestResponseChannel());
            fail("Operation " + restMethod + " should have failed because an external service would have thrown an exception");
        } catch (Exception e) {
            assertEquals("Unexpected exception message", expectedExceptionMsg, e.getMessage());
            if (expectRouterCall && restMethod == RestMethod.GET) {
                assertNotNull("expected router.getBlob() call to provide a response to responseHandler", responseHandler.getResponse());
            }
        }
    }
}
Also used : JSONObject(org.json.JSONObject) MockRestResponseChannel(com.github.ambry.rest.MockRestResponseChannel) ByteBuffer(java.nio.ByteBuffer) BlobId(com.github.ambry.commons.BlobId) JSONException(org.json.JSONException) InvocationTargetException(java.lang.reflect.InvocationTargetException) RestServiceException(com.github.ambry.rest.RestServiceException) IOException(java.io.IOException) RouterException(com.github.ambry.router.RouterException) URISyntaxException(java.net.URISyntaxException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) AccountServiceException(com.github.ambry.account.AccountServiceException) RestMethod(com.github.ambry.rest.RestMethod)

Example 10 with RestMethod

use of com.github.ambry.rest.RestMethod in project ambry by linkedin.

the class FrontendTestUrlSigningServiceFactory method useServiceWithoutStartTest.

/**
 * This tests for exceptions thrown when an {@link FrontendRestRequestService} instance is used without calling
 * {@link FrontendRestRequestService#start()} first.
 * @throws Exception
 */
@Test
public void useServiceWithoutStartTest() throws Exception {
    frontendRestRequestService = getFrontendRestRequestService();
    frontendRestRequestService.setupResponseHandler(responseHandler);
    // not fine to use without start.
    for (RestMethod method : RestMethod.values()) {
        if (method.equals(RestMethod.UNKNOWN)) {
            continue;
        }
        verifyOperationFailure(createRestRequest(method, "/", null, null), RestServiceErrorCode.ServiceUnavailable);
    }
}
Also used : RestMethod(com.github.ambry.rest.RestMethod) Test(org.junit.Test) RestUtilsTest(com.github.ambry.rest.RestUtilsTest) StorageStatsUtilTest(com.github.ambry.server.StorageStatsUtilTest)

Aggregations

RestMethod (com.github.ambry.rest.RestMethod)18 RestServiceException (com.github.ambry.rest.RestServiceException)11 RestRequest (com.github.ambry.rest.RestRequest)9 MockRestRequest (com.github.ambry.rest.MockRestRequest)8 Test (org.junit.Test)8 JSONObject (org.json.JSONObject)6 VerifiableProperties (com.github.ambry.config.VerifiableProperties)5 Properties (java.util.Properties)5 FrontendConfig (com.github.ambry.config.FrontendConfig)4 MockRestResponseChannel (com.github.ambry.rest.MockRestResponseChannel)4 RestUtils (com.github.ambry.rest.RestUtils)4 IOException (java.io.IOException)4 HashMap (java.util.HashMap)4 MetricRegistry (com.codahale.metrics.MetricRegistry)3 BlobId (com.github.ambry.commons.BlobId)3 BlobInfo (com.github.ambry.messageformat.BlobInfo)3 BlobProperties (com.github.ambry.messageformat.BlobProperties)3 RequestPath (com.github.ambry.rest.RequestPath)3 ByteBuffer (java.nio.ByteBuffer)3 Map (java.util.Map)3