diff --git a/examples/BucketExists.hs b/examples/BucketExists.hs index 4a61622..d740d50 100755 --- a/examples/BucketExists.hs +++ b/examples/BucketExists.hs @@ -17,11 +17,11 @@ -- limitations under the License. -- -{-# Language OverloadedStrings #-} -import Network.Minio +{-# LANGUAGE OverloadedStrings #-} +import Network.Minio -import Control.Monad.IO.Class (liftIO) -import Prelude +import Control.Monad.IO.Class (liftIO) +import Prelude -- | The following example uses minio's play server at -- https://play.min.io:9000. The endpoint and associated @@ -39,5 +39,5 @@ main = do liftIO $ putStrLn $ "Does " ++ show bucket ++ " exist? - " ++ show foundBucket case res1 of - Left e -> putStrLn $ "bucketExists failed." ++ show e + Left e -> putStrLn $ "bucketExists failed." ++ show e Right () -> return () diff --git a/minio-hs.cabal b/minio-hs.cabal index 100745f..dae43ed 100644 --- a/minio-hs.cabal +++ b/minio-hs.cabal @@ -56,6 +56,7 @@ library , case-insensitive >= 1.2 , conduit >= 1.3 , conduit-extra >= 1.3 + , connection , containers >= 0.5 , cryptonite >= 0.25 , cryptonite-conduit >= 0.2 @@ -64,6 +65,7 @@ library , exceptions , filepath >= 1.4 , http-client >= 0.5 + , http-client-tls , http-conduit >= 2.3 , http-types >= 0.12 , ini @@ -142,6 +144,7 @@ test-suite minio-hs-live-server-test build-depends: base >= 4.7 && < 5 , minio-hs , protolude >= 0.1.6 + , QuickCheck , aeson , base64-bytestring , binary @@ -149,6 +152,7 @@ test-suite minio-hs-live-server-test , case-insensitive , conduit , conduit-extra + , connection , containers , cryptonite , cryptonite-conduit @@ -157,11 +161,11 @@ test-suite minio-hs-live-server-test , exceptions , filepath , http-client + , http-client-tls , http-conduit , http-types , ini , memory - , QuickCheck , raw-strings-qq >= 1 , resourcet , retry @@ -187,6 +191,7 @@ test-suite minio-hs-test build-depends: base >= 4.7 && < 5 , minio-hs , protolude >= 0.1.6 + , QuickCheck , aeson , base64-bytestring , binary @@ -194,19 +199,20 @@ test-suite minio-hs-test , case-insensitive , conduit , conduit-extra + , connection , containers , cryptonite , cryptonite-conduit - , filepath , digest , directory , exceptions + , filepath , http-client + , http-client-tls , http-conduit , http-types , ini , memory - , QuickCheck , raw-strings-qq >= 1 , resourcet , retry diff --git a/src/Network/Minio.hs b/src/Network/Minio.hs index 2833fa5..635fa84 100644 --- a/src/Network/Minio.hs +++ b/src/Network/Minio.hs @@ -39,6 +39,8 @@ module Network.Minio , setRegion , setCreds , setCredsFrom + , isConnectInfoSecure + , disableTLSCertValidation , MinioConn , mkMinioConn diff --git a/src/Network/Minio/Data.hs b/src/Network/Minio/Data.hs index 4283926..6559492 100644 --- a/src/Network/Minio/Data.hs +++ b/src/Network/Minio/Data.hs @@ -37,7 +37,9 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as TE import Data.Time (defaultTimeLocale, formatTime) import GHC.Show (Show (show)) +import qualified Network.Connection as Conn import Network.HTTP.Client (defaultManagerSettings) +import qualified Network.HTTP.Client.TLS as TLS import qualified Network.HTTP.Conduit as NC import Network.HTTP.Types (ByteRange, Header, Method, Query, hRange) @@ -94,28 +96,30 @@ awsRegionMap = Map.fromList [ -- `IsString` instance to provide a URL, for example: -- -- > let c :: ConnectInfo = "https://play.min.io:9000" -data ConnectInfo = ConnectInfo { - connectHost :: Text - , connectPort :: Int - , connectAccessKey :: Text - , connectSecretKey :: Text - , connectIsSecure :: Bool - , connectRegion :: Region - , connectAutoDiscoverRegion :: Bool - } deriving (Eq, Show) - +data ConnectInfo = + ConnectInfo { connectHost :: Text + , connectPort :: Int + , connectAccessKey :: Text + , connectSecretKey :: Text + , connectIsSecure :: Bool + , connectRegion :: Region + , connectAutoDiscoverRegion :: Bool + , connectDisableTLSCertValidation :: Bool + } deriving (Eq, Show) instance IsString ConnectInfo where - fromString str = let req = NC.parseRequest_ str - in ConnectInfo - { connectHost = TE.decodeUtf8 $ NC.host req - , connectPort = NC.port req - , connectAccessKey = "" - , connectSecretKey = "" - , connectIsSecure = NC.secure req - , connectRegion = "" - , connectAutoDiscoverRegion = True - } + fromString str = + let req = NC.parseRequest_ str + in ConnectInfo + { connectHost = TE.decodeUtf8 $ NC.host req + , connectPort = NC.port req + , connectAccessKey = "" + , connectSecretKey = "" + , connectIsSecure = NC.secure req + , connectRegion = "" + , connectAutoDiscoverRegion = True + , connectDisableTLSCertValidation = False + } -- | Contains access key and secret key to access object storage. data Credentials = Credentials { cAccessKey :: Text @@ -187,6 +191,18 @@ setRegion r connInfo = connInfo { connectRegion = r , connectAutoDiscoverRegion = False } +-- | Check if the connection to object storage server is secure +-- (i.e. uses TLS) +isConnectInfoSecure :: ConnectInfo -> Bool +isConnectInfoSecure = connectIsSecure + +-- | Disable TLS certificate validation completely! This makes TLS +-- insecure! Use only for testing with self-signed or temporary +-- certificates. Note that this option has no effect, if you provide +-- your own Manager in `mkMinioConn`. +disableTLSCertValidation :: ConnectInfo -> ConnectInfo +disableTLSCertValidation c = c { connectDisableTLSCertValidation = True } + getHostAddr :: ConnectInfo -> ByteString getHostAddr ci = if | port == 80 || port == 443 -> toS host | otherwise -> toS $ @@ -955,7 +971,10 @@ instance HasSvcNamespace MinioConn where -- object storage is accessed. connect :: ConnectInfo -> IO MinioConn connect ci = do - let settings | connectIsSecure ci = NC.tlsManagerSettings + let settings | connectIsSecure ci && connectDisableTLSCertValidation ci = + let badTlsSettings = Conn.TLSSettingsSimple True False False + in TLS.mkManagerSettings badTlsSettings Nothing + | connectIsSecure ci = NC.tlsManagerSettings | otherwise = defaultManagerSettings mgr <- NC.newManager settings mkMinioConn ci mgr