/** * Generates an instance of AWS4signerRequestParams that holds the * parameters used for computing a AWS 4 signature for a request */ public AWS4SignerRequestParams(SignableRequest<?> request, Date signingDateOverride, String regionNameOverride, String serviceName, String signingAlgorithm) { if (request == null) { throw new IllegalArgumentException("Request cannot be null"); } if (signingAlgorithm == null) { throw new IllegalArgumentException( "Signing Algorithm cannot be null"); } this.request = request; this.signingDateTimeMilli = signingDateOverride != null ? signingDateOverride .getTime() : getSigningDate(request); this.formattedSigningDate = AWS4SignerUtils .formatDateStamp(signingDateTimeMilli); this.serviceName = serviceName; this.regionName = regionNameOverride != null ? regionNameOverride : AwsHostNameUtils.parseRegionName(request.getEndpoint() .getHost(), this.serviceName); this.scope = generateScope(request, formattedSigningDate, this.serviceName, regionName); this.formattedSigningDateTime = AWS4SignerUtils .formatTimestamp(signingDateTimeMilli); this.signingAlgorithm = signingAlgorithm; }
/** * Creates the authorization header to be included in the request. */ private String buildAuthorizationHeader(SignableRequest<?> request, byte[] signature, AWSCredentials credentials, AWS4SignerRequestParams signerParams) { final String signingCredentials = credentials.getAWSAccessKeyId() + "/" + signerParams.getScope(); final String credential = "Credential=" + signingCredentials; final String signerHeaders = "SignedHeaders=" + getSignedHeadersString(request); final String signatureHeader = "Signature=" + BinaryUtils.toHex(signature); final StringBuilder authHeaderBuilder = new StringBuilder(); authHeaderBuilder.append(AWS4_SIGNING_ALGORITHM) .append(" ") .append(credential) .append(", ") .append(signerHeaders) .append(", ") .append(signatureHeader); return authHeaderBuilder.toString(); }
/** * Includes all the signing headers as request parameters for pre-signing. */ private void addPreSignInformationToRequest(SignableRequest<?> request, AWSCredentials credentials, AWS4SignerRequestParams signerParams, String timeStamp, long expirationInSeconds) { String signingCredentials = credentials.getAWSAccessKeyId() + "/" + signerParams.getScope(); request.addParameter(X_AMZ_ALGORITHM, AWS4_SIGNING_ALGORITHM); request.addParameter(X_AMZ_DATE, timeStamp); request.addParameter(X_AMZ_SIGNED_HEADER, getSignedHeadersString(request)); request.addParameter(X_AMZ_EXPIRES, Long.toString(expirationInSeconds)); request.addParameter(X_AMZ_CREDENTIAL, signingCredentials); }
protected String getCanonicalizedHeaderString(SignableRequest<?> request) { final List<String> sortedHeaders = new ArrayList<String>(request.getHeaders() .keySet()); Collections.sort(sortedHeaders, String.CASE_INSENSITIVE_ORDER); final Map<String, String> requestHeaders = request.getHeaders(); StringBuilder buffer = new StringBuilder(); for (String header : sortedHeaders) { if (shouldExcludeHeaderFromSigning(header)) { continue; } String key = StringUtils.lowerCase(header); String value = requestHeaders.get(header); StringUtils.appendCompactedString(buffer, key); buffer.append(":"); if (value != null) { StringUtils.appendCompactedString(buffer, value); } buffer.append("\n"); } return buffer.toString(); }
protected String getSignedHeadersString(SignableRequest<?> request) { final List<String> sortedHeaders = new ArrayList<String>(request .getHeaders().keySet()); Collections.sort(sortedHeaders, String.CASE_INSENSITIVE_ORDER); StringBuilder buffer = new StringBuilder(); for (String header : sortedHeaders) { if (shouldExcludeHeaderFromSigning(header)) { continue; } if (buffer.length() > 0) buffer.append(";"); buffer.append(StringUtils.lowerCase(header)); } return buffer.toString(); }
/** * Returns the request's payload contents as binary data, without processing * any query string params (i.e. no form encoding for query params). * * @param request * The request * @return The request's payload contents as binary data, not including any * form encoding of query string params. */ protected byte[] getBinaryRequestPayloadWithoutQueryParams(SignableRequest<?> request) { InputStream content = getBinaryRequestPayloadStreamWithoutQueryParams(request); try { ReadLimitInfo info = request.getReadLimitInfo(); content.mark(info == null ? -1 : info.getReadLimit()); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024 * 5]; while (true) { int bytesRead = content.read(buffer); if (bytesRead == -1) break; byteArrayOutputStream.write(buffer, 0, bytesRead); } byteArrayOutputStream.close(); content.reset(); return byteArrayOutputStream.toByteArray(); } catch (Exception e) { throw new SdkClientException("Unable to read request payload to sign request: " + e.getMessage(), e); } }
/** * Creates an encoded query string from all the parameters in the specified * request. * * @param request * The request containing the parameters to encode. * * @return Null if no parameters were present, otherwise the encoded query * string for the parameters present in the specified request. */ public static String encodeParameters(SignableRequest<?> request) { final Map<String, List<String>> requestParams = request.getParameters(); if (requestParams.isEmpty()) return null; final List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); for (Entry<String, List<String>> entry : requestParams.entrySet()) { String parameterName = entry.getKey(); for (String value : entry.getValue()) { nameValuePairs .add(new BasicNameValuePair(parameterName, value)); } } return URLEncodedUtils.format(nameValuePairs, DEFAULT_ENCODING); }
@Test public void testPresigning() throws Exception { final String EXPECTED_AMZ_SIGNATURE = "bf7ae1c2f266d347e290a2aee7b126d38b8a695149d003b9fab2ed1eb6d6ebda"; final String EXPECTED_AMZ_CREDENTIALS = "access/19810216/us-east-1/demo/aws4_request"; final String EXPECTED_AMZ_HEADER = "19810216T063000Z"; final String EXPECTED_AMZ_EXPIRES = "604800"; AWSCredentials credentials = new BasicAWSCredentials("access", "secret"); // Test request without 'x-amz-sha256' header SignableRequest<?> request = generateBasicRequest(); Calendar c = new GregorianCalendar(); c.set(1981, 1, 16, 6, 30, 0); c.setTimeZone(TimeZone.getTimeZone("UTC")); signer.setOverrideDate(c.getTime()); signer.setServiceName("demo"); signer.presignRequest(request, credentials, null); assertEquals(EXPECTED_AMZ_SIGNATURE, request.getParameters().get("X-Amz-Signature").get(0)); assertEquals(EXPECTED_AMZ_CREDENTIALS, request.getParameters().get("X-Amz-Credential").get(0)); assertEquals(EXPECTED_AMZ_HEADER, request.getParameters().get("X-Amz-Date").get(0)); assertEquals(EXPECTED_AMZ_EXPIRES, request.getParameters().get("X-Amz-Expires").get(0)); }
/** * Tests that if passed anonymous credentials, signer will not generate a signature */ @Test public void testAnonymous() throws Exception { AWSCredentials credentials = new AnonymousAWSCredentials(); SignableRequest<?> request = generateBasicRequest(); Calendar c = new GregorianCalendar(); c.set(1981, 1, 16, 6, 30, 0); c.setTimeZone(TimeZone.getTimeZone("UTC")); signer.setServiceName("demo"); signer.setOverrideDate(c.getTime()); signer.sign(request, credentials); assertNull(request.getHeaders().get("Authorization")); }
/** * x-amzn-trace-id should not be signed as it may be mutated by proxies or load balancers. */ @Test public void xAmznTraceId_NotSigned() throws Exception { AWSCredentials credentials = new BasicAWSCredentials("akid", "skid"); SignableRequest<?> request = generateBasicRequest(); request.addHeader("X-Amzn-Trace-Id", " Root=1-584b150a-708479cb060007ffbf3ee1da;Parent=36d3dbcfd150aac9;Sampled=1"); Calendar c = new GregorianCalendar(); c.set(1981, 1, 16, 6, 30, 0); c.setTimeZone(TimeZone.getTimeZone("UTC")); signer.setServiceName("demo"); signer.setOverrideDate(c.getTime()); signer.sign(request, credentials); assertEquals( "AWS4-HMAC-SHA256 Credential=akid/19810216/us-east-1/demo/aws4_request, SignedHeaders=host;x-amz-archive-description;x-amz-date, Signature=581d0042389009a28d461124138f1fe8eeb8daed87611d2a2b47fd3d68d81d73", request.getHeaders().get("Authorization")); }
@Test public void doesNotComputeContentHash_HTTPS() throws UnsupportedEncodingException { SignableRequest<?> request1 = MockRequestBuilder.create() .withEndpoint("https://test-service.example.com") .withContent(new ByteArrayInputStream("CONTENT-1".getBytes("UTF-8"))) .withHeader("headerName", "headerValue") .withParameter("parameterName", "parameterValue") .build(); SignableRequest<?> request2 = MockRequestBuilder.create() .withEndpoint("https://test-service.example.com") .withContent(new ByteArrayInputStream("CONTENT-2".getBytes("UTF-8"))) .withHeader("headerName", "headerValue") .withParameter("parameterName", "parameterValue") .build(); UNSIGNED_PAYLOAD_SIGNER.sign(request1, CREDENTIALS); UNSIGNED_PAYLOAD_SIGNER.sign(request2, CREDENTIALS); assertThat(request1.getHeaders().get("Authorization"), is(equalTo(request2.getHeaders().get("Authorization")))); }
public void sign(SignableRequest<?> request, AWSCredentials credentials) throws SdkClientException { AWSCredentials sanitizedCredentials = sanitizeCredentials(credentials); if ( sanitizedCredentials instanceof AWSSessionCredentials ) { addSessionCredentials(request, (AWSSessionCredentials) sanitizedCredentials); } String expirationInSeconds = Long.toString(expiration.getTime() / 1000L); String canonicalString = RestUtils.makeS3CanonicalString( httpVerb, resourcePath, request, expirationInSeconds); String signature = super.signAndBase64Encode(canonicalString, sanitizedCredentials.getAWSSecretKey(), SigningAlgorithm.HmacSHA1); request.addParameter("AWSAccessKeyId", sanitizedCredentials.getAWSAccessKeyId()); request.addParameter("Expires", expirationInSeconds); request.addParameter("Signature", signature); }
/** * Read the content of the request to get the length of the stream. This * method will wrap the stream by SdkBufferedInputStream if it is not * mark-supported. */ static long getContentLength(SignableRequest<?> request) throws IOException { final InputStream content = request.getContent(); if (!content.markSupported()) throw new IllegalStateException("Bug: request input stream must have been made mark-and-resettable at this point"); ReadLimitInfo info = request.getReadLimitInfo(); final int readLimit = info.getReadLimit(); long contentLength = 0; byte[] tmp = new byte[4096]; int read; content.mark(readLimit); while ((read = content.read(tmp)) != -1) { contentLength += read; } try { content.reset(); } catch(IOException ex) { throw new ResetException("Failed to reset the input stream", ex); } return contentLength; }
public Request apply(SignableRequest<?> signableRequest) { Multimap<String, String> headers = ArrayListMultimap.create(Multimaps.forMap(signableRequest.getHeaders())); headers.put(HttpHeaders.Names.CONTENT_TYPE, HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED); return new RequestBuilder() .setMethod(signableRequest.getHttpMethod().name()) .setUrl(signableRequest.getEndpoint().resolve(signableRequest.getResourcePath()).toString()) .setHeaders(headers.asMap()) .setBody(SdkHttpUtils.encodeParameters(signableRequest)) .build(); }
@Test public void testRequestConversion() throws URISyntaxException { Map<String, String> headers = new HashMap<>(); headers.put(TEST_KEY_A, TEST_VALUE_B); headers.put(TEST_KEY_C, TEST_VALUE_D); Map<String, List<String>> params = new HashMap<>(); params.put(TEST_KEY_A, Collections.singletonList(TEST_VALUE_B)); params.put(TEST_KEY_C, Collections.singletonList(TEST_VALUE_D)); SignableRequest<?> signableRequest = mock(SignableRequest.class); URI endpoint = new URI("http://bandwidth.com"); when(signableRequest.getHttpMethod()).thenReturn(HttpMethodName.GET); when(signableRequest.getEndpoint()).thenReturn(endpoint); when(signableRequest.getResourcePath()).thenReturn(PATH); when(signableRequest.getHeaders()).thenReturn(headers); when(signableRequest.getParameters()).thenReturn(params); Function<SignableRequest<?>, Request> converter = new AsyncRequestConverter(); Request output = converter.apply(signableRequest); assertThat(output.getMethod()).isEqualToIgnoringCase(GET_METHOD); assertThat(output.getUri().getPath()).isEqualTo(PATH); assertThat(output.getHeaders().get(TEST_KEY_A)).isEqualTo(TEST_VALUE_B); assertThat(output.getHeaders().get(TEST_KEY_C)).isEqualTo(TEST_VALUE_D); assertThat(output.getStringData()).isEqualTo(ENCODED_BODY); assertThat(output.getHeaders().get(HttpHeaders.Names.CONTENT_TYPE)) .isEqualTo(HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED); }
/** * This signer will add following authentication parameters to the request: * * AWSAccessKeyId SignatureVersion SignatureMethod Timestamp Signature * * @param request * request to be signed. * * @param version * signature version. "2" is recommended. * * @param algorithm * signature algorithm. "HmacSHA256" is recommended. */ public void sign(SignableRequest<?> request, SignatureVersion version, SigningAlgorithm algorithm, AWSCredentials credentials) throws SdkClientException { // annonymous credentials, don't sign if ( credentials instanceof AnonymousAWSCredentials ) { return; } AWSCredentials sanitizedCredentials = sanitizeCredentials(credentials); request.addParameter("AWSAccessKeyId", sanitizedCredentials.getAWSAccessKeyId()); request.addParameter("SignatureVersion", version.toString()); int timeOffset = request.getTimeOffset(); request.addParameter("Timestamp", getFormattedTimestamp(timeOffset)); if ( sanitizedCredentials instanceof AWSSessionCredentials ) { addSessionCredentials(request, (AWSSessionCredentials) sanitizedCredentials); } String stringToSign = null; if ( version.equals( SignatureVersion.V1 ) ) { stringToSign = calculateStringToSignV1(request.getParameters()); } else if ( version.equals( SignatureVersion.V2 ) ) { request.addParameter("SignatureMethod", algorithm.toString()); stringToSign = calculateStringToSignV2(request); } else { throw new SdkClientException("Invalid Signature Version specified"); } String signatureValue = signAndBase64Encode(stringToSign, sanitizedCredentials.getAWSSecretKey(), algorithm); request.addParameter("Signature", signatureValue); }
/** * Calculate string to sign for signature version 2. * * @param request * The request being signed. * * @return String to sign * * @throws SdkClientException * If the string to sign cannot be calculated. */ private String calculateStringToSignV2(SignableRequest<?> request) throws SdkClientException { URI endpoint = request.getEndpoint(); StringBuilder data = new StringBuilder(); data.append("POST") .append("\n") .append(getCanonicalizedEndpoint(endpoint)) .append("\n") .append(getCanonicalizedResourcePath(request)) .append("\n") .append(getCanonicalizedQueryString(request.getParameters())); return data.toString(); }
private String getCanonicalizedResourcePath(SignableRequest<?> request) { String resourcePath = ""; if (request.getEndpoint().getPath() != null) { resourcePath += request.getEndpoint().getPath(); } if (request.getResourcePath() != null) { if (resourcePath.length() > 0 && !resourcePath.endsWith("/") && !request.getResourcePath().startsWith("/")) { resourcePath += "/"; } resourcePath += request.getResourcePath(); } else if (!resourcePath.endsWith("/")) { resourcePath += "/"; } if (!resourcePath.startsWith("/")) { resourcePath = "/" + resourcePath; } if (resourcePath.startsWith("//")) { resourcePath = resourcePath.substring(1); } return resourcePath; }
@Override protected String calculateContentHash(SignableRequest<?> request) { if ("https".equals(request.getEndpoint().getScheme())) { return "UNSIGNED-PAYLOAD"; } return super.calculateContentHash(request); }
private String getSignedHeadersComponent(SignableRequest<?> request) { StringBuilder builder = new StringBuilder(); builder.append("SignedHeaders="); boolean first = true; for (String header : getHeadersForStringToSign(request)) { if (!first) builder.append(";"); builder.append(header); first = false; } return builder.toString(); }
protected List<String> getHeadersForStringToSign(SignableRequest<?> request) { List<String> headersToSign = new ArrayList<String>(); for (Map.Entry<String, String> entry : request.getHeaders().entrySet()) { String key = entry.getKey(); String lowerCaseKey = StringUtils.lowerCase(key); if (lowerCaseKey.startsWith("x-amz") || lowerCaseKey.equals("host")) { headersToSign.add(key); } } Collections.sort(headersToSign); return headersToSign; }
protected boolean shouldUseHttpsScheme(SignableRequest<?> request) throws SdkClientException { try { String protocol = StringUtils.lowerCase(request.getEndpoint().toURL().getProtocol()); if (protocol.equals("http")) { return false; } else if (protocol.equals("https")) { return true; } else { throw new SdkClientException("Unknown request endpoint protocol " + "encountered while signing request: " + protocol); } } catch (MalformedURLException e) { throw new SdkClientException("Unable to parse request endpoint during signing", e); } }
/** * Returns the scope to be used for the signing. */ private String generateScope(SignableRequest<?> request, String dateStamp, String serviceName, String regionName) { final StringBuilder scopeBuilder = new StringBuilder(); return scopeBuilder.append(dateStamp).append("/").append(regionName) .append("/").append(serviceName).append("/") .append(SignerConstants.AWS4_TERMINATOR).toString(); }
/** * Step 1 of the AWS Signature version 4 calculation. Refer to * http://docs.aws * .amazon.com/general/latest/gr/sigv4-create-canonical-request.html to * generate the canonical request. */ protected String createCanonicalRequest(SignableRequest<?> request, String contentSha256) { /* This would url-encode the resource path for the first time. */ final String path = SdkHttpUtils.appendUri( request.getEndpoint().getPath(), request.getResourcePath()); final StringBuilder canonicalRequestBuilder = new StringBuilder(request .getHttpMethod().toString()); canonicalRequestBuilder.append(LINE_SEPARATOR) // This would optionally double url-encode the resource path .append(getCanonicalizedResourcePath(path, doubleUrlEncode)) .append(LINE_SEPARATOR) .append(getCanonicalizedQueryString(request)) .append(LINE_SEPARATOR) .append(getCanonicalizedHeaderString(request)) .append(LINE_SEPARATOR) .append(getSignedHeadersString(request)).append(LINE_SEPARATOR) .append(contentSha256); final String canonicalRequest = canonicalRequestBuilder.toString(); if (log.isDebugEnabled()) log.debug("AWS4 Canonical Requests: '\"" + canonicalRequest + "\""); return canonicalRequest; }
protected void addHostHeader(SignableRequest<?> request) { // AWS4 requires that we sign the Host header so we // have to have it in the request by the time we sign. final URI endpoint = request.getEndpoint(); final StringBuilder hostHeaderBuilder = new StringBuilder( endpoint.getHost()); if (SdkHttpUtils.isUsingNonDefaultPort(endpoint)) { hostHeaderBuilder.append(":").append(endpoint.getPort()); } request.addHeader(HOST, hostHeaderBuilder.toString()); }
/** * Calculate the hash of the request's payload. Subclass could override this * method to provide different values for "x-amz-content-sha256" header or * do any other necessary set-ups on the request headers. (e.g. aws-chunked * uses a pre-defined header value, and needs to change some headers * relating to content-encoding and content-length.) */ protected String calculateContentHash(SignableRequest<?> request) { InputStream payloadStream = getBinaryRequestPayloadStream(request); ReadLimitInfo info = request.getReadLimitInfo(); payloadStream.mark(info == null ? -1 : info.getReadLimit()); String contentSha256 = BinaryUtils.toHex(hash(payloadStream)); try { payloadStream.reset(); } catch (IOException e) { throw new SdkClientException( "Unable to reset stream after calculating AWS4 signature", e); } return contentSha256; }
protected String getCanonicalizedQueryString(SignableRequest<?> request) { /* * If we're using POST and we don't have any request payload content, * then any request query parameters will be sent as the payload, and * not in the actual query string. */ if (SdkHttpUtils.usePayloadForQueryParameters(request)) return ""; return this.getCanonicalizedQueryString(request.getParameters()); }
/** * Returns the request's payload as binary data. * * @param request * The request * @return The data from the request's payload, as binary data. */ protected byte[] getBinaryRequestPayload(SignableRequest<?> request) { if (SdkHttpUtils.usePayloadForQueryParameters(request)) { String encodedParameters = SdkHttpUtils.encodeParameters(request); if (encodedParameters == null) return new byte[0]; return encodedParameters.getBytes(UTF8); } return getBinaryRequestPayloadWithoutQueryParams(request); }
protected InputStream getBinaryRequestPayloadStream(SignableRequest<?> request) { if (SdkHttpUtils.usePayloadForQueryParameters(request)) { String encodedParameters = SdkHttpUtils.encodeParameters(request); if (encodedParameters == null) return new ByteArrayInputStream(new byte[0]); return new ByteArrayInputStream( encodedParameters.getBytes(UTF8)); } return getBinaryRequestPayloadStreamWithoutQueryParams(request); }
@Test public void testSigning() throws Exception { final String EXPECTED_AUTHORIZATION_HEADER_WITHOUT_SHA256_HEADER = "AWS4-HMAC-SHA256 Credential=access/19810216/us-east-1/demo/aws4_request, SignedHeaders=host;x-amz-archive-description;x-amz-date, Signature=77fe7c02927966018667f21d1dc3dfad9057e58401cbb9ed64f1b7868288e35a"; final String EXPECTED_AUTHORIZATION_HEADER_WITH_SHA256_HEADER = "AWS4-HMAC-SHA256 Credential=access/19810216/us-east-1/demo/aws4_request, SignedHeaders=host;x-amz-archive-description;x-amz-date;x-amz-sha256, Signature=e73e20539446307a5dc71252dbd5b97e861f1d1267456abda3ebd8d57e519951"; AWSCredentials credentials = new BasicAWSCredentials("access", "secret"); // Test request without 'x-amz-sha256' header SignableRequest<?> request = generateBasicRequest(); Calendar c = new GregorianCalendar(); c.set(1981, 1, 16, 6, 30, 0); c.setTimeZone(TimeZone.getTimeZone("UTC")); signer.setOverrideDate(c.getTime()); signer.setServiceName("demo"); signer.sign(request, credentials); assertEquals(EXPECTED_AUTHORIZATION_HEADER_WITHOUT_SHA256_HEADER, request.getHeaders().get("Authorization")); // Test request with 'x-amz-sha256' header request = generateBasicRequest(); request.addHeader("x-amz-sha256", "required"); signer.sign(request, credentials); assertEquals(EXPECTED_AUTHORIZATION_HEADER_WITH_SHA256_HEADER, request.getHeaders().get("Authorization")); }
private SignableRequest<?> generateBasicRequest() { return MockRequestBuilder.create() .withContent(new ByteArrayInputStream("{\"TableName\": \"foo\"}".getBytes())) .withHeader("Host", "demo.us-east-1.amazonaws.com") .withHeader("x-amz-archive-description", "test test") .withPath("/") .withEndpoint("http://demo.us-east-1.amazonaws.com").build(); }
@Test public void computesContentHash_HTTP() throws UnsupportedEncodingException { SignableRequest<?> request = MockRequestBuilder.create() .withEndpoint("http://test-service.example.com") .withHeader("headerName", "headerValue") .withParameter("parameterName", "parameterValue") .withContent(new ByteArrayInputStream("".getBytes("UTF-8"))) .build(); UNSIGNED_PAYLOAD_SIGNER.sign(request, CREDENTIALS); assertThat(request.getHeaders().get(X_AMZ_CONTENT_SHA256), is(equalTo("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"))); }
@Test public void setsContentSha256Header() throws UnsupportedEncodingException { SignableRequest<?> request1 = MockRequestBuilder.create() .withEndpoint("https://test-service.example.com") .withHeader("headerName", "headerValue") .withParameter("parameterName", "parameterValue") .withContent(new ByteArrayInputStream("content".getBytes("UTF-8"))) .build(); UNSIGNED_PAYLOAD_SIGNER.sign(request1, CREDENTIALS); assertThat(request1.getHeaders().get(X_AMZ_CONTENT_SHA256), is(equalTo("UNSIGNED-PAYLOAD"))); }
@Test public void testRequestResourcePath() throws Exception { SignableRequest<?> request = MockRequestBuilder.create() .withEndpoint("http://foo.amazon.com") .withParameter("foo", "bar") .withPath("foo/bar") .build(); signer.sign(request, credentials); assertSignature(EXPECTED_SIGNATURE, request.getParameters()); }
@Test public void testRequestAndEndpointResourcePath() throws Exception { SignableRequest<?> request = MockRequestBuilder.create() .withEndpoint("http://foo.amazon.com/foo") .withParameter("foo", "bar") .withPath("/bar") .build(); signer.sign(request, credentials); assertSignature(EXPECTED_SIGNATURE, request.getParameters()); }
@Test public void testRequestAndEndpointResourcePathNoSlash() throws Exception { SignableRequest<?> request = MockRequestBuilder.create() .withEndpoint("http://foo.amazon.com/foo") .withParameter("foo", "bar") .withPath("bar") .build(); signer.sign(request, credentials); assertSignature(EXPECTED_SIGNATURE, request.getParameters()); }
@Test public void testAnonymous() throws Exception { SignableRequest<?> request = MockRequestBuilder.create() .withEndpoint("http://foo.amazon.com") .withParameter("foo", "bar") .withPath("bar") .build(); signer.sign(request, new AnonymousAWSCredentials()); assertNull(request.getParameters().get("Signature")); }
/** * If necessary, creates a chunk-encoding wrapper on the request payload. */ @Override protected void processRequestPayload(SignableRequest<?> request, byte[] signature, byte[] signingKey, AWS4SignerRequestParams signerRequestParams) { if (useChunkEncoding(request)) { AwsChunkedEncodingInputStream chunkEncodededStream = new AwsChunkedEncodingInputStream( request.getContent(), signingKey, signerRequestParams.getFormattedSigningDateTime(), signerRequestParams.getScope(), BinaryUtils.toHex(signature), this); request.setContent(chunkEncodededStream); } }
/** * Determine whether to use aws-chunked for signing */ private boolean useChunkEncoding(SignableRequest<?> request) { // If chunked encoding is explicitly disabled through client options return right here. // Chunked encoding only makes sense to do when the payload is signed if (!isPayloadSigningEnabled(request) || isChunkedEncodingDisabled(request)) { return false; } if (request.getOriginalRequestObject() instanceof PutObjectRequest || request.getOriginalRequestObject() instanceof UploadPartRequest) { return true; } return false; }
@Override public void sign(SignableRequest<?> request, AWSCredentials credentials) { request.addHeader(name, value); request.addHeader("resourcePath", request.getResourcePath()); }