bloodhound-amazonka-auth 0.1.0.0 → 0.1.1.0
raw patch · 5 files changed
+112/−15 lines, 5 filesdep +aesondep +amazonkadep +http-client-tlsdep ~amazonka-coredep ~amazonka-elasticsearchdep ~bloodhoundPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: aeson, amazonka, http-client-tls, lens, retry, text
Dependency ranges changed: amazonka-core, amazonka-elasticsearch, bloodhound
API changes (from Hackage documentation)
- Database.Bloodhound.Auth.Amazonka.Internal: instance GHC.Classes.Eq Database.Bloodhound.Auth.Amazonka.Internal.EsAmazonkaAuthError
- Database.Bloodhound.Auth.Amazonka.Internal: instance GHC.Exception.Exception Database.Bloodhound.Auth.Amazonka.Internal.EsAmazonkaAuthError
- Database.Bloodhound.Auth.Amazonka.Internal: instance GHC.Show.Show Database.Bloodhound.Auth.Amazonka.Internal.EsAmazonkaAuthError
+ Database.Bloodhound.Auth.Amazonka.Internal: instance Eq EsAmazonkaAuthError
+ Database.Bloodhound.Auth.Amazonka.Internal: instance Exception EsAmazonkaAuthError
+ Database.Bloodhound.Auth.Amazonka.Internal: instance Show EsAmazonkaAuthError
+ Database.Bloodhound.Auth.Amazonka.Internal: instance Typeable EsAmazonkaAuthError
Files
- README.md +1/−0
- bloodhound-amazonka-auth.cabal +11/−4
- changelog.md +5/−0
- src/Database/Bloodhound/Auth/Amazonka/Internal.hs +9/−4
- test/Main.hs +86/−7
README.md view
@@ -1,5 +1,6 @@ # bloodhound-amazonka-auth [](https://travis-ci.org/MichaelXavier/bloodhound-amazonka-auth)+[]() Adds convenient Amazon ElasticSearch Service authentication to Bloodhound.
bloodhound-amazonka-auth.cabal view
@@ -1,5 +1,5 @@ name: bloodhound-amazonka-auth-version: 0.1.0.0+version: 0.1.1.0 synopsis: Adds convenient Amazon ElasticSearch Service authentication to Bloodhound. description: Please see README.md homepage: http://github.com/MichaelXavier/bloodhound-amazonka-auth#readme@@ -26,8 +26,8 @@ , bloodhound >= 0.11 , http-client , time- , amazonka-core >= 1.3.0 && < 1.4- , amazonka-elasticsearch >= 1.3.6 && < 1.4+ , amazonka-core >= 1.3.0 && < 1.5+ , amazonka-elasticsearch >= 1.3.6 && < 1.5 , transformers , http-types , exceptions@@ -52,7 +52,14 @@ , amazonka-core , http-client , time-+ , bloodhound+ , text+ , amazonka+ , amazonka-core+ , http-client-tls+ , lens+ , aeson+ , retry if flag(lib-Werror) ghc-options: -Werror
changelog.md view
@@ -0,0 +1,5 @@+0.1.1.0+* Worked around seemingly a bug in V4 signatures with AWS ES service with paths that needed encoding. This comes up if you make authenticated requests with index patterns, e.g. /foo*/. They would previously fail to authenticate.++0.1.0.0+* Initial release
src/Database/Bloodhound/Auth/Amazonka/Internal.hs view
@@ -3,8 +3,8 @@ -------------------------------------------------------------------------------+import Control.Applicative as A import Control.Exception-import Data.Bifunctor import Data.Time.Clock import Data.Typeable import Database.Bloodhound.Types@@ -37,20 +37,25 @@ -- let bhe = (mkBHEnv server mgr) { bhRequestHook = hook } -- @ amazonkaAuthHook :: AuthEnv -> Region -> Request -> IO (Either EsAmazonkaAuthError Request)-amazonkaAuthHook ae reg req = amazonkaAuthHook' ae reg req <$> getCurrentTime+amazonkaAuthHook ae reg req = amazonkaAuthHook' ae reg req A.<$> getCurrentTime ------------------------------------------------------------------------------- amazonkaAuthHook' :: AuthEnv -> Region -> Request -> UTCTime -> Either EsAmazonkaAuthError Request amazonkaAuthHook' ae reg req now = toReq <$> toAwsRequest req reg where algo = sgSign (A._svcSigner elasticSearch)- toReq req' = sgRequest (algo req' ae reg now)+ toReq req' = decodePath (sgRequest (algo req' ae reg now))+ -- We decode the path because for some reason AWS ES actually+ -- doesn't want the path url encoded. If you do, it will+ -- expect double-encoding for the canonical uri. If you+ -- double, it will expect triple and so-on.+ decodePath x = x { path = urlDecode True (path x)} ------------------------------------------------------------------------------- toAwsRequest :: Request -> Region -> Either EsAmazonkaAuthError (A.Request a) toAwsRequest r reg = do- meth <- first (const badMethod) (parseMethod bsMeth)+ meth <- either (const (Left badMethod)) Right (parseMethod bsMeth) rqb <- toRQBody (requestBody r) q <- toQS (queryString r) return (A.Request { A._rqService = svc
test/Main.hs view
@@ -1,30 +1,96 @@-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-} module Main ( main ) where -------------------------------------------------------------------------------+import Control.Exception+import Control.Lens (set, view)+import Control.Retry+import Data.Aeson+import Data.Monoid+import qualified Data.Proxy as P+import qualified Data.Text as T import Data.Time.Clock.POSIX-import Network.AWS.Types+import Database.Bloodhound+import Network.AWS+import Network.AWS.Env import Network.HTTP.Client+import Network.HTTP.Client.TLS+import System.IO import Test.Tasty import Test.Tasty.HUnit+import Test.Tasty.Options ------------------------------------------------------------------------------- import Database.Bloodhound.Auth.Amazonka.Internal ------------------------------------------------------------------------------- main :: IO ()-main = defaultMain tests+main = defaultMainWithIngredients ings (askOption tests)+ where+ ings = includingOptions [Option (P.Proxy :: P.Proxy IntegrationServer)]:defaultIngredients --------------------------------------------------------------------------------tests :: TestTree-tests = testGroup "bloodhound-amazonka-auth"+tests :: IntegrationServer -> TestTree+tests (IntegrationServer mServer) = testGroup "bloodhound-amazonka-auth" (sharedTests <> integrationTests')+ where+ sharedTests = [amazonkaAuthHookTests]+ integrationTests' = case mServer of+ Just server -> [integrationTests server]+ _ -> []+++-------------------------------------------------------------------------------+integrationTests :: Server -> TestTree+integrationTests server = withResource setup teardown $ \mkEnv -> testGroup "integration" [- amazonkaAuthHookTests+ testCase "authenticates request" $ do+ env <- mkEnv+ exists <- runBH env $ indexExists testIndex+ exists @?= True+ -- Index patterns add a * to the path, which can wreak havoc if not+ -- accounted for in AWS V4 signing.+ , testCase "authenticates when using index patterns" $ do+ env <- mkEnv+ let search = Search {+ queryBody = Nothing+ , filterBody = Nothing+ , sortBody = Nothing+ , aggBody = Nothing+ , highlight = Nothing+ , trackSortScores = False+ , from = From 0+ , size = Size 0+ , searchType = SearchTypeQueryThenFetch+ , fields = Nothing+ , source = Nothing+ }+ res <- parseEsResponse =<< runBH env (searchByIndex testIndexSplat search)+ case (res :: Either EsError (SearchResult Value)) of+ Right _ -> return ()+ Left e -> assertFailure (show e) ]+ where+ testIndex = IndexName "bloodhound-amazonka-auth-test"+ testIndexSplat = IndexName "bloodhound-amazonka-auth-test*"+ ixs = IndexSettings (ShardCount 1) (ReplicaCount 0)+ setup = do+ mgr <- newManager tlsManagerSettings+ lgr <- newLogger Debug stdout+ env <- set envLogger lgr<$> newEnvWith region Discover Nothing mgr+ let auth = view envAuth env+ let hook req = withAuth auth $ \authEnv -> either throwIO return =<< amazonkaAuthHook authEnv region req+ let bhe = (mkBHEnv server mgr) { bhRequestHook = hook }+ _ <- runBH bhe (createIndex ixs testIndex)+ True <- retrying (constantDelay 5000 <> limitRetries 5) (\_ exists -> return (not exists)) (\_ -> runBH bhe (indexExists testIndex))+ return bhe+ -- could make this customizable if we cared to+ region = NorthVirginia+ teardown bhe = either (\(_ :: SomeException) -> ()) (const ()) <$> try (runBH bhe (deleteIndex testIndex)) -------------------------------------------------------------------------------@@ -32,7 +98,7 @@ amazonkaAuthHookTests = testGroup "amazonkaAuthHook" [ testCase "does not mangle query parameters" $ do- req <- parseUrl "http://localhost:9200/foo/foo/_search?scroll=1m&search_type=scan"+ req <- parseUrlThrow "http://localhost:9200/foo/foo/_search?scroll=1m&search_type=scan" let ae = AuthEnv (AccessKey "access key") (SecretKey "secret key") Nothing Nothing let now = posixSecondsToUTCTime 0 let Right res = amazonkaAuthHook' ae NorthVirginia req now@@ -42,3 +108,16 @@ path res @?= "/foo/foo/_search" queryString res @?= "?scroll=1m&search_type=scan" ]+++-------------------------------------------------------------------------------+newtype IntegrationServer = IntegrationServer (Maybe Server)+ deriving (Show, Eq)+++instance IsOption IntegrationServer where+ defaultValue = IntegrationServer Nothing+ parseValue "" = return (IntegrationServer Nothing)+ parseValue s = return (IntegrationServer (Just (Server (T.pack s))))+ optionName = return "integration-server"+ optionHelp = return "If supplied, tests against a real AWS ES cluster (fees may apply). Uses the standard amazonka methods for discovering credentials."