问题
I'm using the aws managed elasticsearch/ I'm using the high-level java client for elastic search. Is there a way to use aws signature4 signing for the requests made with the high level client?
回答1:
All you need to do perform the signing calculations and add the appropriate headers to your request. See Examples: Signature Calculations in AWS Signature Version 4 for Java and C# examples. I took took this code and put my own interface on top:
import net.craigcaulfield.awsutils.signing.auth.AWS4SignerBase;
import net.craigcaulfield.awsutils.signing.auth.AWS4SignerForAuthorizationHeader;
import net.craigcaulfield.awsutils.signing.util.BinaryUtils;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
/**
* A utility for calculating an AWS Signature Version 4 signature headers for requests. See
* http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-examples-using-sdks.html for the full description.
*
* @author Craig Caulfield
*/
public class SigningUtility {
/**
* Build the authorization headers to be added to the service request.
*
* @param regionName AWS region
* @param url service URL
* @param awsAccessKey AWS access key
* @param awsSecretKey AWS secret key
* @param messageBody the message body for POSTs
* @param httpMethod the HTTP verb used for this message (GET, POST, etc)
* @param serviceName the AWS service (s3, execite-api, ...)
* @return authorisation headers to add to the request.
*/
public Map<String, String> getAuthorisationHeader(String regionName, String url, String awsAccessKey, String awsSecretKey,
String messageBody, String httpMethod, String serviceName) {
URL endpointUrl;
try {
endpointUrl = new URL(url);
} catch (MalformedURLException e) {
throw new RuntimeException("Unable to parse service endpoint: " + e.getMessage());
}
String contentHashString;
Map<String, String> headers = new HashMap<>();
if ("POST".equals(httpMethod)) {
// precompute hash of the body content
byte[] contentHash = AWS4SignerBase.hash(messageBody);
contentHashString = BinaryUtils.toHex(contentHash);
headers.put("x-amz-content-sha256", contentHashString);
headers.put("content-length", "" + messageBody.length());
} else if ("GET".equals(httpMethod)) {
contentHashString = AWS4SignerBase.EMPTY_BODY_SHA256;
// for a simple GET, we have no body so supply the precomputed 'empty' hash
headers.put("x-amz-content-sha256", AWS4SignerBase.EMPTY_BODY_SHA256);
} else {
throw new UnsupportedOperationException("This utility only supports GET and POST HTTP verbs for now");
}
AWS4SignerForAuthorizationHeader signer = new AWS4SignerForAuthorizationHeader(
endpointUrl, httpMethod, serviceName, regionName);
String authorisation = signer.computeSignature(headers,
null, // assume no query parameters
contentHashString,
awsAccessKey,
awsSecretKey);
headers.put("Authorization", authorisation);
return headers;
}
}
The AWS4SignerBase, AWS4SignerForAuthorizationHeader, BinaryUtils classes come directly from the AWS example. The only hard bit is finding the serviceName for your particular service, which for Elastic Search is probably es.
As an alternative, if you can make use of (and afford soapUI Pro), it has built-in features to do all this for you.
来源:https://stackoverflow.com/questions/51544966/signature4-signing-for-elastic-search-in-aws