mirror of https://github.com/apache/cloudstack.git
Auth correct for uploads
This commit is contained in:
parent
6b6877b3cb
commit
df4eb587c2
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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" );
|
||||
|
|
|
|||
Loading…
Reference in New Issue