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

Auth user check - EDAPI #423

Merged
merged 32 commits into from
May 2, 2019
Merged
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f3c827d
Add query for claim sub
sajidanower23 Apr 16, 2019
d740d45
Remove redundant imports
sajidanower23 Apr 17, 2019
b84d597
Add abstraction for running db operations
sajidanower23 Apr 17, 2019
42dab2f
Add error type, introduce error hierarchy
sajidanower23 Apr 17, 2019
8a52255
Style tweaks
sajidanower23 Apr 17, 2019
ae3dbbf
Implement FromField StringOrURI
sajidanower23 Apr 17, 2019
9887a50
Add function to add users
sajidanower23 Apr 17, 2019
0398210
Remove unused debug function
sajidanower23 Apr 18, 2019
2e35982
Run stylish-haskell through some BR modules
sajidanower23 Apr 18, 2019
d0b1b3d
Style tweaks
sajidanower23 Apr 18, 2019
299ce39
Add different app modes; add way to bootstrap users into the database
sajidanower23 Apr 18, 2019
eed3dcc
Bugfix bootstrap to allow bootstrapping without an auth user
sajidanower23 Apr 18, 2019
fc8f0c3
Add comment
sajidanower23 Apr 18, 2019
ed86c56
Actually use the bootstrap function
sajidanower23 Apr 18, 2019
cbea350
Complete Var instance for AppMode
sajidanower23 Apr 23, 2019
0fd2de5
Use putStrLn instead of print
sajidanower23 Apr 23, 2019
ce7a4e8
Merge branch 'master' of github.com:data61/Mirza into auth-user-check…
sajidanower23 Apr 30, 2019
f95c93e
Tweak dockerfile
sajidanower23 Apr 30, 2019
6197dc1
List workdir
sajidanower23 May 1, 2019
8737ae3
Use text instead of varchar
sajidanower23 May 1, 2019
4c0c3b8
Make errors a new module
sajidanower23 May 1, 2019
dfb8406
Remove redundant wildcard
sajidanower23 May 1, 2019
b295e1b
Add further error types
sajidanower23 May 1, 2019
669d1b6
Throw proper errors instead of returning Bool
sajidanower23 May 1, 2019
4fd0b3e
Store adding user's creds in case of db insertion fails for unauth ac…
sajidanower23 May 1, 2019
5f4c184
Make dir /edapi
sajidanower23 May 2, 2019
3dff9b3
Use LambdaCase
sajidanower23 May 2, 2019
51ddfd4
Add more log in Dockerfile
sajidanower23 May 2, 2019
1baaee3
Run mkdir before setting it as workdir
sajidanower23 May 2, 2019
d7b77db
Put /edapi in /src
sajidanower23 May 2, 2019
4453d01
Remove FROM flag
sajidanower23 May 2, 2019
bcc80dc
Add further log
sajidanower23 May 2, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add different app modes; add way to bootstrap users into the database
sajidanower23 committed Apr 18, 2019
commit 299ce393480a8563a79bdcc677629f307a9ac8e0
108 changes: 76 additions & 32 deletions projects/entity-data-api/src/Mirza/EntityDataAPI/Main.hs
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
{-# LANGUAGE LambdaCase #-}

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Mirza.EntityDataAPI.Main (main) where

import System.Envy (decodeEnv)
import System.Envy (decodeEnv)

import Options.Applicative

import Network.HTTP.Client (newManager)
import Network.HTTP.Client.TLS (tlsManagerSettings)
import Network.HTTP.Client (newManager)
import Network.HTTP.Client.TLS (tlsManagerSettings)

import Mirza.EntityDataAPI.AuthProxy (runAuthProxy)
import Mirza.EntityDataAPI.AuthProxy (runAuthProxy)
import Mirza.EntityDataAPI.Database.Utils (addUserSub)
import Mirza.EntityDataAPI.Types
import Mirza.EntityDataAPI.Utils (fetchJWKs)
import Mirza.EntityDataAPI.Utils (fetchJWKs)

import Network.HTTP.ReverseProxy (ProxyDest (..))
import qualified Network.Wai.Handler.Warp as Warp

import Network.HTTP.ReverseProxy (ProxyDest (..))
import qualified Network.Wai.Handler.Warp as Warp
import qualified Data.ByteString.Char8 as B

import qualified Data.ByteString.Char8 as B
import Data.String (IsString (..))

import Data.String (IsString (..))
import Crypto.JWT (StringOrURI)

import Database.PostgreSQL.Simple (close, connectPostgreSQL)
import Database.PostgreSQL.Simple (close, connectPostgreSQL)

import Data.Pool (createPool)
import Data.Pool (createPool)

import Control.Monad (void)

main :: IO ()
-- main = launchProxy =<< execParser opts where
@@ -35,11 +40,51 @@ main = (decodeEnv :: IO (Either String Opts)) >>= \case
Left err -> fail $ "Failed to parse Opts: " <> err
Right opts -> do
print opts
launchProxy opts
multiplexInitOptions opts

multiplexInitOptions :: Opts -> IO ()
multiplexInitOptions opts = do
ctx <- initContext opts
putStrLn $ "Initialized context. Starting app on mode " <> (show . appMode $ opts)
case appMode opts of
Proxy -> launchProxy ctx
API -> launchUserManager ctx
Bootstrap -> do
res <- tryAddUser ctx
print res


promptLine :: String -> IO String
promptLine prompt = do
putStr prompt
getLine


tryAddUser :: AuthContext -> IO (Either AppError Bool)
tryAddUser ctx = do
(authorisedUserStr :: String) <- promptLine "Enter thy creds: "
(toAddUserStr :: String) <- promptLine "User you want to add: "
let (authorisedUserSub :: StringOrURI) = fromString authorisedUserStr
let (toAddUserSub :: StringOrURI) = fromString toAddUserStr
res <- runAppM ctx $ addUserSub authorisedUserSub toAddUserSub
case res of
Right True -> print $ "Successfully added user"
Right False -> print "Failed to add the user."
Left err -> print $ "Failed with error : " <> show err
pure res

launchUserManager :: AuthContext -> IO () -- run the UserManager.main in an infinite loop
launchUserManager ctx = do
res <- tryAddUser ctx
launchUserManager ctx
-- case res of
-- Right True -> launchUserManager ctx
-- Left err -> launchUserManager ctx


initContext :: Opts -> IO AuthContext
initContext (Opts myService (ServiceInfo (Hostname destHost) (Port destPort)) url clientId dbConnStr) = do
initContext (Opts myService (ServiceInfo (Hostname destHost) (Port destPort)) _mode url clientId dbConnStr) = do
putStrLn "Initializing context..."
let proxyDest = ProxyDest (B.pack destHost) destPort
mngr <- newManager tlsManagerSettings
connpool <- createPool (connectPostgreSQL dbConnStr) close
@@ -50,24 +95,23 @@ initContext (Opts myService (ServiceInfo (Hostname destHost) (Port destPort)) ur
Left err -> fail $ show err
Right jwkSet -> pure $ AuthContext myService proxyDest mngr jwkSet (fromString clientId) connpool

launchProxy :: Opts -> IO ()
launchProxy opts = do
putStrLn "Initializing context..."
ctx <- initContext opts
launchProxy :: AuthContext -> IO ()
launchProxy ctx = do
putStrLn $ "Starting service on " <>
(getHostname . serviceHost . myProxyServiceInfo $ ctx) <> ":" <>
(show . servicePort . myProxyServiceInfo $ ctx)
(show . getPort . servicePort . myProxyServiceInfo $ ctx)
Warp.run (fromIntegral . getPort . servicePort . myProxyServiceInfo $ ctx) (runAuthProxy ctx)

_optsParser :: Parser Opts
_optsParser = Opts
<$> (ServiceInfo
<$> (Hostname <$> strOption (long "host" <> short 'h' <> value "localhost" <> showDefault <> help "The host to run this service on."))
<*> (Port <$> option auto (long "port" <> short 'p' <> value 8000 <> showDefault <> help "The port to run this service on."))
)
<*> (ServiceInfo
<$> (Hostname <$> strOption (long "desthost" <> short 'd' <> value "localhost" <> showDefault <> help "The host to make requests to."))
<*> (Port <$> option auto (long "destport" <> short 'r' <> value 8200 <> showDefault <> help "Port to make requests to.")))
<*> strOption (long "jwkurl" <> short 'j' <> value "https://mirza.au.auth0.com/.well-known/jwks.json" <> showDefault <> help "URL to fetch ")
<*> strOption (long "jwkclientid" <> short 'k' <> help "Audience Claim.")
<*> strOption (long "conn" <> short 'c' <> help "Postgresql DB Connection String")
-- _optsParser :: Parser Opts
-- _optsParser = Opts
-- <$> (ServiceInfo
-- <$> (Hostname <$> strOption (long "host" <> short 'h' <> value "localhost" <> showDefault <> help "The host to run this service on."))
-- <*> (Port <$> option auto (long "port" <> short 'p' <> value 8000 <> showDefault <> help "The port to run this service on."))
-- )
-- <*> (ServiceInfo
-- <$> (Hostname <$> strOption (long "desthost" <> short 'd' <> value "localhost" <> showDefault <> help "The host to make requests to."))
-- <*> (Port <$> option auto (long "destport" <> short 'r' <> value 8200 <> showDefault <> help "Port to make requests to.")))
-- <*> (strOption (long "mode" <> short 'm' <> value Proxy <> showDefault <> help "Mode to run the app on. Available modes: Proxy | API"))
-- <*> strOption (long "jwkurl" <> short 'j' <> value "https://mirza.au.auth0.com/.well-known/jwks.json" <> showDefault <> help "URL to fetch ")
-- <*> strOption (long "jwkclientid" <> short 'k' <> help "Audience Claim.")
-- <*> strOption (long "conn" <> short 'c' <> help "Postgresql DB Connection String")
13 changes: 13 additions & 0 deletions projects/entity-data-api/src/Mirza/EntityDataAPI/Types.hs
Original file line number Diff line number Diff line change
@@ -114,9 +114,20 @@ defaultJwkUrl = "https://mirza.au.auth0.com/.well-known/jwks.json"

-- ----------------Opts----------------------------


data AppMode
= Proxy
| API -- placeholder
| Bootstrap
deriving (Show, Eq, Generic, Read)

instance Var AppMode where
fromVar m = readMaybe m :: Maybe AppMode

data Opts = Opts
{ myServiceInfo :: ServiceInfo
, destServiceInfo :: ServiceInfo
, appMode :: AppMode
, jwkUrl :: String
, jwkClientId :: String
, dbConnectionStr :: ByteString
@@ -126,6 +137,7 @@ instance DefConfig Opts where
defConfig = Opts
{ myServiceInfo = ServiceInfo{serviceHost=Hostname "localhost", servicePort=Port 8080 }
, destServiceInfo = ServiceInfo{serviceHost=Hostname "localhost", servicePort=Port 8000 }
, appMode = Proxy
, jwkUrl = defaultJwkUrl
, jwkClientId = ""
, dbConnectionStr = "dbname=deventitydataapi"
@@ -135,6 +147,7 @@ instance FromEnv Opts where
fromEnv = Opts
<$> fromEnvMyServiceInfo
<*> fromEnvDestServiceInfo
<*> envMaybe "EDAPI_MODE" .!= Proxy
<*> envMaybe "JWK_URL" .!= defaultJwkUrl
<*> env "JWK_CLIENT_ID"
<*> env "EDAPI_DB_CONN"