// -> note that the Servlet engine will un-URL encode all parameters we extract via "getParameterValues()" calls
String[] awsAccess = request.getParameterValues( "AWSAccessKeyId" );
if ( null != awsAccess && 0 < awsAccess.length )
cloudAccessKey = awsAccess[0];
else {
throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - AWSAccessKeyId");
}
String[] clientSig = request.getParameterValues( "Signature" );
if ( null != clientSig && 0 < clientSig.length )
signature = clientSig[0];
else {
throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Signature");
}
String[] method = request.getParameterValues( "SignatureMethod" );
if ( null != method && 0 < method.length )
{
sigMethod = method[0];
if (!sigMethod.equals( "HmacSHA256" ) && !sigMethod.equals( "HmacSHA1" )) {
throw new EC2ServiceException( ClientError.InvalidParameterValue,
"Unsupported SignatureMethod value: " + sigMethod + " expecting: HmacSHA256 or HmacSHA1");
}
} else {
throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - SignatureMethod");
}
String[] version = request.getParameterValues( "Version" );
if ( null != version && 0 < version.length )
{
if (!version[0].equals( wsdlVersion )) {
throw new EC2ServiceException( ClientError.InvalidParameterValue,
"Unsupported Version value: " + version[0] + " expecting: " + wsdlVersion);
}
} else {
throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - Version");
}
String[] sigVersion = request.getParameterValues( "SignatureVersion" );
if ( null != sigVersion && 0 < sigVersion.length )
{
if (!sigVersion[0].equals( "2" )) {
throw new EC2ServiceException( ClientError.InvalidParameterValue,
"Unsupported SignatureVersion value: " + sigVersion[0] + " expecting: 2");
}
}
else {
throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter - SignatureVersion");
}
// -> can have only one but not both { Expires | Timestamp } headers
String[] expires = request.getParameterValues( "Expires" );
if ( null != expires && 0 < expires.length )
{
// -> contains the date and time at which the signature included in the request EXPIRES
if (hasSignatureExpired( expires[0] )) { //InvalidSecurity.RequestHasExpired
throw new EC2ServiceException( ClientError.InvalidSecurity_RequestHasExpired,
"Expires parameter indicates signature has expired: " + expires[0]);
}
}
else
{ // -> contains the date and time at which the request is SIGNED
String[] time = request.getParameterValues( "Timestamp" );
if ( null == time || 0 == time.length ) {
throw new EC2ServiceException( ClientError.MissingParamter, "Missing required parameter -" +
" Timestamp/Expires");
}
}
// [B] Use the access key to get the users secret key from the cloud DB
cloudSecretKey = userDao.getSecretKeyByAccessKey( cloudAccessKey );
if ( cloudSecretKey == null ) {
logger.debug( "Access key '" + cloudAccessKey + "' not found in the the EC2 service ");
throw new EC2ServiceException( ClientError.AuthFailure, "Access key '" + cloudAccessKey + "' not found in the the EC2 service ");
}
// [C] Verify the signature
// -> getting the query-string in this way maintains its URL encoding
EC2RestAuth restAuth = new EC2RestAuth();
restAuth.setHostHeader( request.getHeader( "Host" ));
String requestUri = request.getRequestURI();
// If forwarded from another basepath:
String forwardedPath = (String) request.getAttribute("javax.servlet.forward.request_uri");
if(forwardedPath!=null){
requestUri=forwardedPath;
}
restAuth.setHTTPRequestURI( requestUri);
String queryString = request.getQueryString();
// getQueryString returns null (does it ever NOT return null for these),
// we need to construct queryString to avoid changing the auth code...
if (queryString == null) {
// construct our idea of a queryString with parameters!
Enumeration<?> params = request.getParameterNames();
if (params != null) {
while(params.hasMoreElements()) {
String paramName = (String) params.nextElement();
// exclude the signature string obviously. ;)
if (paramName.equalsIgnoreCase("Signature")) continue;
// URLEncoder performs application/x-www-form-urlencoded-type encoding and not Percent encoding
// according to RFC 3986 as required by Amazon, we need to Percent-encode (URL Encode)
String encodedValue = URLEncoder.encode(request.getParameter(paramName), "UTF-8")
.replace("+", "%20").replace("*", "%2A");
if (queryString == null)
queryString = paramName + "=" + encodedValue;
else
queryString = queryString + "&" + paramName + "=" + encodedValue;
}
}
}
restAuth.setQueryString(queryString);
if ( restAuth.verifySignature( request.getMethod(), cloudSecretKey, signature, sigMethod )) {
UserContext.current().initContext( cloudAccessKey, cloudSecretKey, cloudAccessKey, "REST request", null );
return true;
}
else throw new EC2ServiceException( ClientError.SignatureDoesNotMatch,
"The request signature calculated does not match the signature provided by the user.");
}