Add port to host header for signing. (#24)

* Add port to host header for signing.

* Use endpoint corresponding to region for AWS S3
This commit is contained in:
Krishnan Parthasarathi 2017-03-03 21:16:47 +05:30 committed by Aditya Manthramurthy
parent c30d4b2ce5
commit 9001f81813
4 changed files with 33 additions and 15 deletions

View File

@ -17,13 +17,12 @@
-- limitations under the License. -- limitations under the License.
-- --
{-# Language OverloadedStrings #-} {-# Language OverloadedStrings #-}
import Network.Minio import Network.Minio
import qualified Data.Conduit as C import Data.Conduit (($$+-))
import qualified Data.Conduit.Binary as CB import Data.Conduit.Binary (sinkLbs)
import Prelude import Prelude
-- | The following example uses minio's play server at -- | The following example uses minio's play server at
-- https://play.minio.io:9000. The endpoint and associated -- https://play.minio.io:9000. The endpoint and associated
@ -35,10 +34,12 @@ import Prelude
main :: IO () main :: IO ()
main = do main = do
let let
bucket = "krisis" bucket = "my-bucket"
object = "fail.out" object = "my-object"
res <- runResourceT $ runMinio minioPlayCI $ do res <- runResourceT $ runMinio minioPlayCI $ do
(_, src) <- getObject bucket object [] [] src <- getObject bucket object
(src C.$$+- CB.sinkLbs) (src $$+- sinkLbs)
print res case res of
Left e -> putStrLn $ "getObject failed." ++ (show e)
Right _ -> putStrLn "getObject succeeded."

View File

@ -28,6 +28,7 @@ import qualified Data.Conduit as C
import Data.Conduit.Binary (sourceHandleRange) import Data.Conduit.Binary (sourceHandleRange)
import Data.Default (def) import Data.Default (def)
import qualified Data.Map as Map import qualified Data.Map as Map
import qualified Data.Text as T
import Network.HTTP.Conduit (Response) import Network.HTTP.Conduit (Response)
import qualified Network.HTTP.Conduit as NC import qualified Network.HTTP.Conduit as NC
import qualified Network.HTTP.Types as HT import qualified Network.HTTP.Types as HT
@ -36,6 +37,7 @@ import Lib.Prelude
import Network.Minio.Data import Network.Minio.Data
import Network.Minio.Data.Crypto import Network.Minio.Data.Crypto
import Network.Minio.Errors
import Network.Minio.Sign.V4 import Network.Minio.Sign.V4
import Network.Minio.Utils import Network.Minio.Utils
import Network.Minio.XmlParser import Network.Minio.XmlParser
@ -104,20 +106,33 @@ buildRequest ri = do
return $ Just $ connectRegion ci return $ Just $ connectRegion ci
| otherwise -> discoverRegion ri | otherwise -> discoverRegion ri
regionHost <- case region of
Nothing -> return $ connectHost ci
Just r -> if "amazonaws.com" `T.isSuffixOf` (connectHost ci)
then maybe
(throwM $ ME $ ValidationError $ MErrVRegionNotSupported r)
return
(Map.lookup r awsRegionMap)
else return $ connectHost ci
sha256Hash <- getPayloadSHA256Hash (riPayload ri) sha256Hash <- getPayloadSHA256Hash (riPayload ri)
let newRi = ri { let newRi = ri {
riPayloadHash = sha256Hash riPayloadHash = sha256Hash
, riHeaders = sha256Header sha256Hash : (riHeaders ri) , riHeaders = sha256Header sha256Hash : (riHeaders ri)
, riRegion = region , riRegion = region
} }
newCi = ci {
connectHost = regionHost
}
reqHeaders <- liftIO $ signV4 ci newRi reqHeaders <- liftIO $ signV4 newCi newRi
return NC.defaultRequest { return NC.defaultRequest {
NC.method = riMethod newRi NC.method = riMethod newRi
, NC.secure = connectIsSecure ci , NC.secure = connectIsSecure newCi
, NC.host = encodeUtf8 $ connectHost ci , NC.host = encodeUtf8 $ connectHost newCi
, NC.port = connectPort ci , NC.port = connectPort newCi
, NC.path = getPathFromRI newRi , NC.path = getPathFromRI newRi
, NC.queryString = HT.renderQuery False $ riQueryParams newRi , NC.queryString = HT.renderQuery False $ riQueryParams newRi
, NC.requestHeaders = reqHeaders , NC.requestHeaders = reqHeaders

View File

@ -33,6 +33,7 @@ data MErrV = MErrVSinglePUTSizeExceeded Int64
| MErrVInvalidSrcObjSpec Text | MErrVInvalidSrcObjSpec Text
| MErrVInvalidSrcObjByteRange (Int64, Int64) | MErrVInvalidSrcObjByteRange (Int64, Int64)
| MErrVCopyObjSingleNoRangeAccepted | MErrVCopyObjSingleNoRangeAccepted
| MErrVRegionNotSupported Text
deriving (Show, Eq) deriving (Show, Eq)
-- | Errors thrown by the library -- | Errors thrown by the library

View File

@ -98,7 +98,8 @@ signV4AtTime ts ci ri =
outHeaders = authHeader : headersWithDate outHeaders = authHeader : headersWithDate
timeBS = awsTimeFormatBS ts timeBS = awsTimeFormatBS ts
dateHeader = (mk "X-Amz-Date", timeBS) dateHeader = (mk "X-Amz-Date", timeBS)
hostHeader = (mk "host", encodeUtf8 $ connectHost ci) hostHeader = (mk "host", encodeUtf8 $ format "{}:{}" $
[connectHost ci, show $ connectPort ci])
headersWithDate = dateHeader : hostHeader : (riHeaders ri) headersWithDate = dateHeader : hostHeader : (riHeaders ri)