diff --git a/cloudbridge/src/com/cloud/bridge/service/S3RestServlet.java b/cloudbridge/src/com/cloud/bridge/service/S3RestServlet.java index f0b5896b3c7..90cbb9697a9 100644 --- a/cloudbridge/src/com/cloud/bridge/service/S3RestServlet.java +++ b/cloudbridge/src/com/cloud/bridge/service/S3RestServlet.java @@ -296,7 +296,7 @@ public class S3RestServlet extends HttpServlet { auth.setHostHeader( request.getHeader( "Host" )); auth.setQueryString( request.getQueryString()); auth.addUriPath( request.getRequestURI()); - + // -> are their any Amazon specific (i.e. 'x-amz-' ) headers? HeaderParam[] headers = params.getHeaders(); for( int i=0; null != headers && i < headers.length; i++ ) diff --git a/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java b/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java index a41d538696b..dfb21e9ccf9 100644 --- a/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java +++ b/cloudbridge/src/com/cloud/bridge/service/controller/s3/S3BucketAction.java @@ -757,6 +757,7 @@ public class S3BucketAction implements ServletAction { } public void executePutBucketWebsite(HttpServletRequest request, HttpServletResponse response) throws IOException { + // TODO -- HiPri - Implement Put Bucket Website response.setStatus(501); } @@ -770,7 +771,7 @@ public class S3BucketAction implements ServletAction { } /** - * This is a very complex function with all the options defined by Amazon. Part of the functionality is + * This is a complex function with all the options defined by Amazon. Part of the functionality is * provided by the query done against the database. The CommonPrefixes functionality is done the same way * as done in the listBucketContents function (i.e., by iterating though the list to decide which output * element each key is placed). diff --git a/cloudbridge/src/com/cloud/bridge/util/RestAuth.java b/cloudbridge/src/com/cloud/bridge/util/RestAuth.java index b71729577e3..5941f44c266 100755 --- a/cloudbridge/src/com/cloud/bridge/util/RestAuth.java +++ b/cloudbridge/src/com/cloud/bridge/util/RestAuth.java @@ -40,7 +40,7 @@ public class RestAuth { // TreeMap: used when constructing the CanonicalizedAmzHeaders Element of the StringToSign protected TreeMap AmazonHeaders = null; // not always present protected String bucketName = null; // not always present - protected String queryString = null; // only interested in a small set of values + protected String queryString = null; // for CanonicalizedResource - only interested in a string starting with particular values protected String uriPath = null; // only interested in the resource path protected String date = null; // only if x-amz-date is not set protected String contentType = null; // not always present @@ -94,7 +94,6 @@ public class RestAuth { /** * Value is used in constructing the StringToSign for signature verification. - * * @param type - the contents of the "Content-MD5:" header, skipping the 'Content-MD5:' preamble. */ public void setContentMD5Header( String md5 ) { @@ -128,7 +127,11 @@ public class RestAuth { /** * Used as part of the CanonalizedResource element of the StringToSign. - * + * CanonicalizedResource = [ "/" + Bucket ] + + * + [sub-resource] + * The list of sub-resources that must be included when constructing the CanonicalizedResource Element are: acl, lifecycle, location, + * logging, notification, partNumber, policy, requestPayment, torrent, uploadId, uploads, versionId, versioning, versions and website. + * (http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html) * @param query - results from calling "HttpServletRequest req.getQueryString()" */ public void setQueryString( String query ) { @@ -140,12 +143,17 @@ public class RestAuth { query = new String( "?" + query.trim()); // -> only interested in this subset of parameters - if (query.startsWith( "?versioning") || query.startsWith( "?location" ) || - query.startsWith( "?acl" ) || query.startsWith( "?torrent" )) { + 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" ) + ) + { - // -> include any value (i.e., with '=') and chop of the rest - int offset = query.indexOf( "&" ); - if ( -1 != offset ) query = query.substring( 0, offset ); + // 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; } } @@ -264,13 +272,15 @@ public class RestAuth { private String genStringToSign( String httpVerb ) { StringBuffer canonicalized = new StringBuffer(); String temp = null; + String canonicalizedResourceElement = genCanonicalizedResourceElement(); + canonicalized.append( httpVerb ).append( "\n" ); - if (null != this.contentMD5) + if ( (null != this.contentMD5) && (null == canonicalizedResourceElement) ) canonicalized.append( this.contentMD5 ); canonicalized.append( "\n" ); - if (null != this.contentType) + if ( (null != this.contentType) && (null == canonicalizedResourceElement) ) canonicalized.append( this.contentType ); canonicalized.append( "\n" ); @@ -280,7 +290,7 @@ public class RestAuth { canonicalized.append( "\n" ); if (null != (temp = genCanonicalizedAmzHeadersElement())) canonicalized.append( temp ); - if (null != (temp = genCanonicalizedResourceElement() )) canonicalized.append( temp ); + if (null != canonicalizedResourceElement) canonicalized.append( canonicalizedResourceElement ); if ( 0 == canonicalized.length()) return null;