Auth correct for uploads

This commit is contained in:
JohnZ 2012-04-27 09:04:56 +01:00 committed by Salvatore Orlando
parent 6b6877b3cb
commit df4eb587c2
5 changed files with 65 additions and 37 deletions

0
cloudbridge/deploy-cloud-bridge.sh Normal file → Executable file
View File

View File

@ -311,7 +311,7 @@ public class S3RestServlet extends HttpServlet {
if (info == null) throw new PermissionDeniedException("Unable to authenticate access key: " + AWSAccessKey);
try {
if (auth.verifySignature( request.getMethod(), info.getSecretKey(), signature )) {
if (auth.verifySignature( request.getMethod(), info.getSecretKey(), signature )) {
UserContext.current().initContext(AWSAccessKey, info.getSecretKey(), AWSAccessKey, info.getDescription(), request);
return;
}

View File

@ -604,19 +604,19 @@ public class S3BucketAction implements ServletAction {
public void executeGetBucketLogging(HttpServletRequest request, HttpServletResponse response) throws IOException {
// TODO -- this is a beta feature of S3
response.setStatus(501);
response.setStatus(405);
}
public void executeGetBucketLocation(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setStatus(501);
response.setStatus(405);
}
public void executeGetBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setStatus(501);
response.setStatus(405);
}
public void executeDeleteBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setStatus(501);
response.setStatus(405);
}
public void executePutBucket(HttpServletRequest request, HttpServletResponse response) throws IOException
@ -757,8 +757,11 @@ public class S3BucketAction implements ServletAction {
}
public void executePutBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException {
// TODO -- HiPri - Implement Put Bucket Website
response.setStatus(501);
// TODO -- HiPri - Undertake checks on Put Bucket Website
// Tested using configuration <Directory /Users/john1/S3-Mount>\nAllowOverride FileInfo AuthConfig Limit...</Directory> in httpd.conf
// Need some way of using AllowOverride to allow use of .htaccess and then pushing .httaccess file to bucket subdirectory of mount point
// Currently has noop effect in the sense that a running apachectl process sees the directory contents without further action
response.setStatus(200);
}
public void executeDeleteBucket(HttpServletRequest request, HttpServletResponse response) throws IOException

View File

@ -105,7 +105,7 @@ public class S3ObjectAction implements ServletAction {
throws IOException, XMLStreamException
{
String method = request.getMethod();
String queryString = request.getQueryString();
String queryString = request.getQueryString();
String copy = null;
response.addHeader( "x-amz-request-id", UUID.randomUUID().toString());
@ -143,9 +143,9 @@ public class S3ObjectAction implements ServletAction {
}
else executeDeleteObject(request, response);
}
else if (method.equalsIgnoreCase( "HEAD" ))
{
executeHeadObject(request, response);
else if (method.equalsIgnoreCase( "HEAD" ))
{
executeHeadObject(request, response);
}
else if (method.equalsIgnoreCase( "POST" ))
{
@ -302,7 +302,8 @@ public class S3ObjectAction implements ServletAction {
private void executeGetObject(HttpServletRequest request, HttpServletResponse response) throws IOException
{
String bucket = (String) request.getAttribute(S3Constants.BUCKET_ATTR_KEY);
String key = (String) request.getAttribute(S3Constants.OBJECT_ATTR_KEY);
String key = (String) request.getAttribute(S3Constants.OBJECT_ATTR_KEY);
S3GetObjectRequest engineRequest = new S3GetObjectRequest();
engineRequest.setBucketName(bucket);
@ -713,8 +714,10 @@ public class S3ObjectAction implements ServletAction {
String cannedAccess = null;
int uploadId = -1;
// -> Amazon defines to keep connection alive by sending whitespace characters until done
// AWS S3 specifies that the keep alive connection is by sending whitespace characters until done
// Therefore the XML version prolog is prepended to the stream in advance
OutputStream os = response.getOutputStream();
os.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>".getBytes());
String temp = request.getParameter("uploadId");
if (null != temp) uploadId = Integer.parseInt( temp );
@ -781,7 +784,8 @@ public class S3ObjectAction implements ServletAction {
xml.append( "<Key>" ).append( key ).append( "</Key>" );
xml.append( "<ETag>\"" ).append( engineResponse.getETag()).append( "\"</<ETag>" );
xml.append( "</CompleteMultipartUploadResult>" );
os.write( xml.toString().getBytes());
String xmlString = xml.toString().replaceAll("^\\s+", ""); // Remove leading whitespace characters
os.write( xmlString.getBytes());
os.close();
}
else returnErrorXML( result, null, os );

View File

@ -48,14 +48,33 @@ public class RestAuth {
protected boolean amzDateSet = false;
protected boolean useSubDomain = false;
protected Set<String> allowedQueryParams;
public RestAuth() {
// these must be lexicographically sorted
AmazonHeaders = new TreeMap<String, String>();
allowedQueryParams = new HashSet<String>() {{
add("acl");
add("lifecycle");
add("location");
add("logging");
add("notification");
add("partNumber");
add("policy");
add("requestPayment");
add("torrent");
add("uploadId");
add("uploads");
add("versionId");
add("versioning");
add("versions");
add("website");
}};
}
public RestAuth(boolean useSubDomain) {
// these must be lexicographically sorted
AmazonHeaders = new TreeMap<String, String>();
//invoke the other constructor
this();
this.useSubDomain = useSubDomain;
}
@ -140,22 +159,28 @@ public class RestAuth {
return;
}
query = new String( "?" + query.trim());
// Sub-resources (i.e.: query params) must be lex sorted
Set<String> subResources = new TreeSet<String>();
// -> only interested in this subset of parameters
if (query.startsWith( "?acl") || query.startsWith( "?lifecycle" ) || query.startsWith( "?location" ) ||
query.startsWith( "?logging" ) || query.startsWith( "?notification" ) || query.startsWith( "?partNumber" ) ||
query.startsWith( "?policy" ) || query.startsWith( "?requestPayment" ) || query.startsWith( "?torrent" ) ||
query.startsWith( "?uploadId" ) || query.startsWith( "?uploads" ) || query.startsWith( "?versionId" ) ||
query.startsWith( "?versioning" ) || query.startsWith( "?versions" ) || query.startsWith( "?website" )
)
{
// The query string includes the value given to the start parameter (using =) but ignores all other arguments after &
int offset = query.indexOf( "&" );
if ( -1 != offset ) query = query.substring( 0, offset );
this.queryString = query;
String [] queryParams = query.split("&");
StringBuffer builtQuery= new StringBuffer();
for (String queryParam:queryParams) {
// lookup parameter name
String paramName = queryParam.split("=")[0];
if (allowedQueryParams.contains(paramName)) {
subResources.add(queryParam);
}
}
for (String subResource:subResources) {
builtQuery.append(subResource + "&");
}
// If anything inside the string buffer, add a "?" at the beginning,
// and then remove the last '&'
if (builtQuery.length() > 0) {
builtQuery.insert(0, "?");
builtQuery.deleteCharAt(builtQuery.length()-1);
}
this.queryString = builtQuery.toString();
}
@ -235,7 +260,7 @@ public class RestAuth {
throws SignatureException, UnsupportedEncodingException {
if (null == httpVerb || null == secretKey || null == signature) return false;
httpVerb = httpVerb.trim();
secretKey = secretKey.trim();
signature = signature.trim();
@ -243,7 +268,6 @@ public class RestAuth {
// First calculate the StringToSign after the caller has initialized all the header values
String StringToSign = genStringToSign( httpVerb );
String calSig = calculateRFC2104HMAC( StringToSign, secretKey );
// Was the passed in signature URL encoded? (it must be base64 encoded)
int offset = signature.indexOf( "%" );
if (-1 != offset) signature = URLDecoder.decode( signature, "UTF-8" );
@ -273,14 +297,12 @@ public class RestAuth {
StringBuffer canonicalized = new StringBuffer();
String temp = null;
String canonicalizedResourceElement = genCanonicalizedResourceElement();
canonicalized.append( httpVerb ).append( "\n" );
if ( (null != this.contentMD5) && (null == canonicalizedResourceElement) )
if ( (null != this.contentMD5) )
canonicalized.append( this.contentMD5 );
canonicalized.append( "\n" );
if ( (null != this.contentType) && (null == canonicalizedResourceElement) )
if ( (null != this.contentType) )
canonicalized.append( this.contentType );
canonicalized.append( "\n" );
@ -356,7 +378,6 @@ public class RestAuth {
*/
private String calculateRFC2104HMAC( String signIt, String secretKey )
throws SignatureException {
String result = null;
try {
SecretKeySpec key = new SecretKeySpec( secretKey.getBytes(), "HmacSHA1" );