Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

s3SignQuery Issue #54

Closed
ckw opened this issue Dec 21, 2012 · 2 comments
Closed

s3SignQuery Issue #54

ckw opened this issue Dec 21, 2012 · 2 comments
Assignees
Labels
Milestone

Comments

@ckw
Copy link
Contributor

ckw commented Dec 21, 2012

If you look at s3SignQuery in Aws/S3/Core.hs

s3SignQuery :: S3Query -> S3Configuration qt -> SignatureData -> SignedQuery            
s3SignQuery S3Query{..} S3Configuration{..} SignatureData{..}                           
    = SignedQuery {                                                                     
        sqMethod = s3QMethod                                                         
      , sqProtocol = s3Protocol                                                         
      , sqHost = B.intercalate "." $ catMaybes host                                     
      , sqPort = s3Port                                                                 
      , sqPath = mconcat $ catMaybes path                                                                                            
      , sqQuery = sortedSubresources ++ s3QQuery ++ authQuery :: HTTP.Query          
      , sqDate = Just signatureTime                                                     
      , sqAuthorization = authorization                                                 
      , sqContentType = s3QContentType                                                  
      , sqContentMd5 = s3QContentMd5                                                    
      , sqAmzHeaders = amzHeaders                                                       
      , sqOtherHeaders = s3QOtherHeaders                                                
      , sqBody = s3QRequestBody                                                         
      , sqStringToSign = stringToSign                                                
      }

You'll see that

sqQuery = sortedSubresources ++ s3QQuery ++ authQuery :: HTTP.Query 

differs from its form in the stringToSign

HTTP.renderQueryBuilder True sortedSubresources

This hasn't been an issue because all of the commands that can set the s3QQuery field
to something other than an empty list do not do so in practice.

Example: in GetObject

  s3QQuery = HTTP.toQuery [                         
         ("response-content-type" :: B8.ByteString,) <$> goResponseContentType
       , ("response-content-language",) <$> goResponseContentLanguage
       , ("response-expires",) <$> goResponseExpires
       , ("response-cache-control",) <$> goResponseCacheControl
       , ("response-content-disposition",) <$> goResponseContentDisposition
       , ("response-content-encoding",) <$> goResponseContentEncoding
       ] 

In practice, people must use getObject

getObject :: Bucket -> T.Text -> GetObject                                           
getObject b o = GetObject b o Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing

I ran into this issue writing DeleteObjects. Putting "delete" in the s3QQuery doesn't work. Making the obvious fix to the stringToSign process broke another command, (GetBucket?), so I just put it in s3QSubresources as a hack.

Test case that should generate a 403 (slightly modified version of the GetObject example):

{-# LANGUAGE OverloadedStrings #-}                                                                                                   

import qualified Aws                                                                                                                 
import qualified Aws.S3 as S3                                                                                                        
import qualified Aws.S3.Commands.GetObject as G                                                                                      
import           Data.Conduit (($$+-))                                                                                               
import           Data.Conduit.Binary (sinkFile)                                                                                      
import           Network.HTTP.Conduit (withManager, responseBody)                                                                    

main :: IO ()                                                                                                                        
main = do                                                                                                                            
  {- Set up AWS credentials and the default configuration. -}                                                                        
  cfg <- Aws.baseConfiguration                                                                                                       
  let s3cfg = Aws.defServiceConfig :: S3.S3Configuration Aws.NormalQuery                                                             

  {- Set up a ResourceT region with an available HTTP manager. -}                                                                    
  withManager $ \mgr -> do                                                                                                           
    {- Create a request object with S3.getObject and run the request with pureAws. -}                                                
    S3.GetObjectResponse { S3.gorResponse = rsp } <-                                                                                 
      Aws.pureAws cfg s3cfg mgr $                                                                                                    
        (S3.getObject "haskell-aws" "cloud-remote.pdf") { G.goResponseCacheControl = Just "300" }                                    

    {- Save the response to a file. -}                                                                                               
    responseBody rsp $$+- sinkFile "cloud-remote.pdf"
@aristidb
Copy link
Owner

Looks like a case of inaccurate AWS documentation: http://docs.amazonwebservices.com/AmazonS3/latest/dev/RESTAuthentication.html#ConstructingTheAuthenticationHeader

Unless I am mistaken, our code is faithful to the documentation, but of course that's simply not how S3 actually behaves.

I guess I'll experiment with it a little.

@ghost ghost assigned jwiegley Apr 28, 2013
@aristidb
Copy link
Owner

Should be fixed as of ea83a89

aristidb added a commit that referenced this issue Aug 31, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants