packages feed

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 view
@@ -1,5 +1,6 @@ # bloodhound-amazonka-auth [![Build Status](https://travis-ci.org/MichaelXavier/bloodhound-amazonka-auth.svg?branch=master)](https://travis-ci.org/MichaelXavier/bloodhound-amazonka-auth)+[![Hackage](https://img.shields.io/hackage/v/bloodhound-amazonka-auth.svg)]()  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."