{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
module Aws.Iam.Core
( iamSignQuery
, iamResponseConsumer
, IamMetadata(..)
, IamConfiguration(..)
, IamError(..)
, parseDateTime
, AccessKeyStatus(..)
, User(..)
, parseUser
, Group(..)
, parseGroup
, MfaDevice(..)
, parseMfaDevice
) where
import Aws.Core
import qualified Blaze.ByteString.Builder as Blaze
import qualified Blaze.ByteString.Builder.Char8 as Blaze8
import Control.Exception (Exception)
import Control.Monad
import Control.Monad.Trans.Resource (MonadThrow, throwM)
import Data.ByteString (ByteString)
import Data.IORef
import Data.List (intersperse, sort)
import Data.Maybe
import Data.Monoid ()
import qualified Data.Semigroup as Sem
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Time
import Data.Typeable
import qualified Network.HTTP.Conduit as HTTP
import qualified Network.HTTP.Types as HTTP
#if !MIN_VERSION_time(1,5,0)
import System.Locale
#endif
import Text.XML.Cursor (($//))
import qualified Text.XML.Cursor as Cu
data IamError
= IamError {
IamError -> Status
iamStatusCode :: HTTP.Status
, IamError -> Text
iamErrorCode :: Text
, IamError -> Text
iamErrorMessage :: Text
}
deriving (Int -> IamError -> ShowS
[IamError] -> ShowS
IamError -> String
(Int -> IamError -> ShowS)
-> (IamError -> String) -> ([IamError] -> ShowS) -> Show IamError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IamError] -> ShowS
$cshowList :: [IamError] -> ShowS
show :: IamError -> String
$cshow :: IamError -> String
showsPrec :: Int -> IamError -> ShowS
$cshowsPrec :: Int -> IamError -> ShowS
Show, Typeable)
instance Exception IamError
data IamMetadata
= IamMetadata {
IamMetadata -> Maybe Text
requestId :: Maybe Text
}
deriving (Int -> IamMetadata -> ShowS
[IamMetadata] -> ShowS
IamMetadata -> String
(Int -> IamMetadata -> ShowS)
-> (IamMetadata -> String)
-> ([IamMetadata] -> ShowS)
-> Show IamMetadata
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IamMetadata] -> ShowS
$cshowList :: [IamMetadata] -> ShowS
show :: IamMetadata -> String
$cshow :: IamMetadata -> String
showsPrec :: Int -> IamMetadata -> ShowS
$cshowsPrec :: Int -> IamMetadata -> ShowS
Show, Typeable)
instance Loggable IamMetadata where
toLogText :: IamMetadata -> Text
toLogText (IamMetadata Maybe Text
r) = Text
"IAM: request ID=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
Sem.<> Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"<none>" Maybe Text
r
instance Sem.Semigroup IamMetadata where
IamMetadata Maybe Text
r1 <> :: IamMetadata -> IamMetadata -> IamMetadata
<> IamMetadata Maybe Text
r2 = Maybe Text -> IamMetadata
IamMetadata (Maybe Text
r1 Maybe Text -> Maybe Text -> Maybe Text
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` Maybe Text
r2)
instance Monoid IamMetadata where
mempty :: IamMetadata
mempty = Maybe Text -> IamMetadata
IamMetadata Maybe Text
forall a. Maybe a
Nothing
mappend :: IamMetadata -> IamMetadata -> IamMetadata
mappend = IamMetadata -> IamMetadata -> IamMetadata
forall a. Semigroup a => a -> a -> a
(Sem.<>)
data IamConfiguration qt
= IamConfiguration {
IamConfiguration qt -> ByteString
iamEndpoint :: ByteString
, IamConfiguration qt -> Int
iamPort :: Int
, IamConfiguration qt -> Protocol
iamProtocol :: Protocol
, IamConfiguration qt -> Method
iamHttpMethod :: Method
}
deriving (Int -> IamConfiguration qt -> ShowS
[IamConfiguration qt] -> ShowS
IamConfiguration qt -> String
(Int -> IamConfiguration qt -> ShowS)
-> (IamConfiguration qt -> String)
-> ([IamConfiguration qt] -> ShowS)
-> Show (IamConfiguration qt)
forall qt. Int -> IamConfiguration qt -> ShowS
forall qt. [IamConfiguration qt] -> ShowS
forall qt. IamConfiguration qt -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IamConfiguration qt] -> ShowS
$cshowList :: forall qt. [IamConfiguration qt] -> ShowS
show :: IamConfiguration qt -> String
$cshow :: forall qt. IamConfiguration qt -> String
showsPrec :: Int -> IamConfiguration qt -> ShowS
$cshowsPrec :: forall qt. Int -> IamConfiguration qt -> ShowS
Show)
instance DefaultServiceConfiguration (IamConfiguration NormalQuery) where
defServiceConfig :: IamConfiguration NormalQuery
defServiceConfig = Method -> Protocol -> ByteString -> IamConfiguration NormalQuery
forall qt. Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
PostQuery Protocol
HTTPS ByteString
iamEndpointDefault
debugServiceConfig :: IamConfiguration NormalQuery
debugServiceConfig = Method -> Protocol -> ByteString -> IamConfiguration NormalQuery
forall qt. Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
PostQuery Protocol
HTTP ByteString
iamEndpointDefault
instance DefaultServiceConfiguration (IamConfiguration UriOnlyQuery) where
defServiceConfig :: IamConfiguration UriOnlyQuery
defServiceConfig = Method -> Protocol -> ByteString -> IamConfiguration UriOnlyQuery
forall qt. Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
Get Protocol
HTTPS ByteString
iamEndpointDefault
debugServiceConfig :: IamConfiguration UriOnlyQuery
debugServiceConfig = Method -> Protocol -> ByteString -> IamConfiguration UriOnlyQuery
forall qt. Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
Get Protocol
HTTP ByteString
iamEndpointDefault
iamEndpointDefault :: ByteString
iamEndpointDefault :: ByteString
iamEndpointDefault = ByteString
"iam.amazonaws.com"
iam :: Method -> Protocol -> ByteString -> IamConfiguration qt
iam :: Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
method Protocol
protocol ByteString
endpoint
= IamConfiguration :: forall qt.
ByteString -> Int -> Protocol -> Method -> IamConfiguration qt
IamConfiguration {
iamEndpoint :: ByteString
iamEndpoint = ByteString
endpoint
, iamProtocol :: Protocol
iamProtocol = Protocol
protocol
, iamPort :: Int
iamPort = Protocol -> Int
defaultPort Protocol
protocol
, iamHttpMethod :: Method
iamHttpMethod = Method
method
}
iamSignQuery
:: [(ByteString, ByteString)]
-> IamConfiguration qt
-> SignatureData
-> SignedQuery
iamSignQuery :: [(ByteString, ByteString)]
-> IamConfiguration qt -> SignatureData -> SignedQuery
iamSignQuery [(ByteString, ByteString)]
q IamConfiguration{Int
ByteString
Method
Protocol
iamHttpMethod :: Method
iamProtocol :: Protocol
iamPort :: Int
iamEndpoint :: ByteString
iamHttpMethod :: forall qt. IamConfiguration qt -> Method
iamProtocol :: forall qt. IamConfiguration qt -> Protocol
iamPort :: forall qt. IamConfiguration qt -> Int
iamEndpoint :: forall qt. IamConfiguration qt -> ByteString
..} SignatureData{UTCTime
AbsoluteTimeInfo
Credentials
signatureCredentials :: SignatureData -> Credentials
signatureTime :: SignatureData -> UTCTime
signatureTimeInfo :: SignatureData -> AbsoluteTimeInfo
signatureCredentials :: Credentials
signatureTime :: UTCTime
signatureTimeInfo :: AbsoluteTimeInfo
..}
= SignedQuery :: Method
-> Protocol
-> ByteString
-> Int
-> ByteString
-> Query
-> Maybe UTCTime
-> Maybe (IO ByteString)
-> Maybe ByteString
-> Maybe (Digest MD5)
-> RequestHeaders
-> RequestHeaders
-> Maybe RequestBody
-> ByteString
-> SignedQuery
SignedQuery {
sqMethod :: Method
sqMethod = Method
iamHttpMethod
, sqProtocol :: Protocol
sqProtocol = Protocol
iamProtocol
, sqHost :: ByteString
sqHost = ByteString
iamEndpoint
, sqPort :: Int
sqPort = Int
iamPort
, sqPath :: ByteString
sqPath = ByteString
"/"
, sqQuery :: Query
sqQuery = Query
signedQuery
, sqDate :: Maybe UTCTime
sqDate = UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
signatureTime
, sqAuthorization :: Maybe (IO ByteString)
sqAuthorization = Maybe (IO ByteString)
forall a. Maybe a
Nothing
, sqContentType :: Maybe ByteString
sqContentType = Maybe ByteString
forall a. Maybe a
Nothing
, sqContentMd5 :: Maybe (Digest MD5)
sqContentMd5 = Maybe (Digest MD5)
forall a. Maybe a
Nothing
, sqAmzHeaders :: RequestHeaders
sqAmzHeaders = []
, sqOtherHeaders :: RequestHeaders
sqOtherHeaders = []
, sqBody :: Maybe RequestBody
sqBody = Maybe RequestBody
forall a. Maybe a
Nothing
, sqStringToSign :: ByteString
sqStringToSign = ByteString
stringToSign
}
where
sig :: ByteString
sig = Credentials -> AuthorizationHash -> ByteString -> ByteString
signature Credentials
signatureCredentials AuthorizationHash
HmacSHA256 ByteString
stringToSign
signedQuery :: Query
signedQuery = (ByteString
"Signature", ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
sig)(ByteString, Maybe ByteString) -> Query -> Query
forall a. a -> [a] -> [a]
:Query
expandedQuery
accessKey :: ByteString
accessKey = Credentials -> ByteString
accessKeyID Credentials
signatureCredentials
timestampHeader :: (ByteString, Maybe ByteString)
timestampHeader =
case AbsoluteTimeInfo
signatureTimeInfo of
AbsoluteTimestamp UTCTime
time -> (ByteString
"Timestamp", ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ UTCTime -> ByteString
fmtAmzTime UTCTime
time)
AbsoluteExpires UTCTime
time -> (ByteString
"Expires" , ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ UTCTime -> ByteString
fmtAmzTime UTCTime
time)
newline :: Builder
newline = Char -> Builder
Blaze8.fromChar Char
'\n'
stringToSign :: ByteString
stringToSign = Builder -> ByteString
Blaze.toByteString (Builder -> ByteString)
-> ([Builder] -> Builder) -> [Builder] -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder)
-> ([Builder] -> [Builder]) -> [Builder] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
intersperse Builder
newline ([Builder] -> ByteString) -> [Builder] -> ByteString
forall a b. (a -> b) -> a -> b
$
(ByteString -> Builder) -> [ByteString] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Builder
Blaze.copyByteString
[Method -> ByteString
httpMethod Method
iamHttpMethod, ByteString
iamEndpoint, ByteString
"/"]
[Builder] -> [Builder] -> [Builder]
forall a. [a] -> [a] -> [a]
++ [Bool -> Query -> Builder
HTTP.renderQueryBuilder Bool
False Query
expandedQuery]
expandedQuery :: Query
expandedQuery = Query -> Query
forall a. QueryLike a => a -> Query
HTTP.toQuery (Query -> Query) -> (Query -> Query) -> Query -> Query
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Query -> Query
forall a. Ord a => [a] -> [a]
sort (Query -> Query) -> Query -> Query
forall a b. (a -> b) -> a -> b
$ (((ByteString, ByteString) -> (ByteString, Maybe ByteString))
-> [(ByteString, ByteString)] -> Query
forall a b. (a -> b) -> [a] -> [b]
map (\(ByteString
a,ByteString
b) -> (ByteString
a, ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
b)) [(ByteString, ByteString)]
q Query -> Query -> Query
forall a. [a] -> [a] -> [a]
++) [
(ByteString
"AWSAccessKeyId" , ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
accessKey)
, (ByteString
"SignatureMethod" , ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ AuthorizationHash -> ByteString
amzHash AuthorizationHash
HmacSHA256)
, (ByteString
"SignatureVersion", ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
"2")
, (ByteString
"Version" , ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
"2010-05-08")
, (ByteString, Maybe ByteString)
timestampHeader] Query -> Query -> Query
forall a. [a] -> [a] -> [a]
++
Query -> (ByteString -> Query) -> Maybe ByteString -> Query
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\ByteString
tok -> [ (ByteString
"SecurityToken", ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
tok)]) (Credentials -> Maybe ByteString
iamToken Credentials
signatureCredentials)
iamResponseConsumer :: (Cu.Cursor -> Response IamMetadata a)
-> IORef IamMetadata
-> HTTPResponseConsumer a
iamResponseConsumer :: (Cursor -> Response IamMetadata a)
-> IORef IamMetadata -> HTTPResponseConsumer a
iamResponseConsumer Cursor -> Response IamMetadata a
inner IORef IamMetadata
md Response (ConduitM () ByteString (ResourceT IO) ())
resp = (Cursor -> Response IamMetadata a)
-> IORef IamMetadata -> HTTPResponseConsumer a
forall m a.
Monoid m =>
(Cursor -> Response m a) -> IORef m -> HTTPResponseConsumer a
xmlCursorConsumer Cursor -> Response IamMetadata a
parse IORef IamMetadata
md Response (ConduitM () ByteString (ResourceT IO) ())
resp
where
parse :: Cursor -> Response IamMetadata a
parse Cursor
cursor = do
let rid :: Maybe Text
rid = [Text] -> Maybe Text
forall a. [a] -> Maybe a
listToMaybe ([Text] -> Maybe Text) -> [Text] -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Cursor
cursor Cursor -> (Cursor -> [Text]) -> [Text]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
"RequestID"
IamMetadata -> Response IamMetadata ()
forall m. m -> Response m ()
tellMetadata (IamMetadata -> Response IamMetadata ())
-> IamMetadata -> Response IamMetadata ()
forall a b. (a -> b) -> a -> b
$ Maybe Text -> IamMetadata
IamMetadata Maybe Text
rid
case Cursor
cursor Cursor -> (Cursor -> [Cursor]) -> [Cursor]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Cursor]
Cu.laxElement Text
"Error" of
[] -> Cursor -> Response IamMetadata a
inner Cursor
cursor
(Cursor
err:[Cursor]
_) -> Cursor -> Response IamMetadata a
fromError Cursor
err
fromError :: Cursor -> Response IamMetadata a
fromError Cursor
cursor = do
Text
errCode <- String -> [Text] -> Response IamMetadata Text
forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force String
"Missing Error Code" ([Text] -> Response IamMetadata Text)
-> [Text] -> Response IamMetadata Text
forall a b. (a -> b) -> a -> b
$ Cursor
cursor Cursor -> (Cursor -> [Text]) -> [Text]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
"Code"
Text
errMsg <- String -> [Text] -> Response IamMetadata Text
forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force String
"Missing Error Message" ([Text] -> Response IamMetadata Text)
-> [Text] -> Response IamMetadata Text
forall a b. (a -> b) -> a -> b
$ Cursor
cursor Cursor -> (Cursor -> [Text]) -> [Text]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
"Message"
IamError -> Response IamMetadata a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (IamError -> Response IamMetadata a)
-> IamError -> Response IamMetadata a
forall a b. (a -> b) -> a -> b
$ Status -> Text -> Text -> IamError
IamError (Response (ConduitM () ByteString (ResourceT IO) ()) -> Status
forall body. Response body -> Status
HTTP.responseStatus Response (ConduitM () ByteString (ResourceT IO) ())
resp) Text
errCode Text
errMsg
parseDateTime :: MonadThrow m => String -> m UTCTime
parseDateTime :: String -> m UTCTime
parseDateTime String
x
= case Bool -> TimeLocale -> String -> String -> Maybe UTCTime
forall (m :: * -> *) t.
(MonadFail m, ParseTime t) =>
Bool -> TimeLocale -> String -> String -> m t
parseTimeM Bool
True TimeLocale
defaultTimeLocale String
iso8601UtcDate String
x of
Maybe UTCTime
Nothing -> XmlException -> m UTCTime
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (XmlException -> m UTCTime) -> XmlException -> m UTCTime
forall a b. (a -> b) -> a -> b
$ String -> XmlException
XmlException (String -> XmlException) -> String -> XmlException
forall a b. (a -> b) -> a -> b
$ String
"Invalid DateTime: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
x
Just UTCTime
dt -> UTCTime -> m UTCTime
forall (m :: * -> *) a. Monad m => a -> m a
return UTCTime
dt
data User
= User {
User -> Text
userArn :: Text
, User -> UTCTime
userCreateDate :: UTCTime
, User -> Text
userPath :: Text
, User -> Text
userUserId :: Text
, User -> Text
userUserName :: Text
}
deriving (User -> User -> Bool
(User -> User -> Bool) -> (User -> User -> Bool) -> Eq User
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: User -> User -> Bool
$c/= :: User -> User -> Bool
== :: User -> User -> Bool
$c== :: User -> User -> Bool
Eq, Eq User
Eq User
-> (User -> User -> Ordering)
-> (User -> User -> Bool)
-> (User -> User -> Bool)
-> (User -> User -> Bool)
-> (User -> User -> Bool)
-> (User -> User -> User)
-> (User -> User -> User)
-> Ord User
User -> User -> Bool
User -> User -> Ordering
User -> User -> User
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: User -> User -> User
$cmin :: User -> User -> User
max :: User -> User -> User
$cmax :: User -> User -> User
>= :: User -> User -> Bool
$c>= :: User -> User -> Bool
> :: User -> User -> Bool
$c> :: User -> User -> Bool
<= :: User -> User -> Bool
$c<= :: User -> User -> Bool
< :: User -> User -> Bool
$c< :: User -> User -> Bool
compare :: User -> User -> Ordering
$ccompare :: User -> User -> Ordering
$cp1Ord :: Eq User
Ord, Int -> User -> ShowS
[User] -> ShowS
User -> String
(Int -> User -> ShowS)
-> (User -> String) -> ([User] -> ShowS) -> Show User
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [User] -> ShowS
$cshowList :: [User] -> ShowS
show :: User -> String
$cshow :: User -> String
showsPrec :: Int -> User -> ShowS
$cshowsPrec :: Int -> User -> ShowS
Show, Typeable)
parseUser :: MonadThrow m => Cu.Cursor -> m User
parseUser :: Cursor -> m User
parseUser Cursor
cursor = do
Text
userArn <- Text -> m Text
attr Text
"Arn"
UTCTime
userCreateDate <- Text -> m Text
attr Text
"CreateDate" m Text -> (Text -> m UTCTime) -> m UTCTime
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> m UTCTime
forall (m :: * -> *). MonadThrow m => String -> m UTCTime
parseDateTime (String -> m UTCTime) -> (Text -> String) -> Text -> m UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack
Text
userPath <- Text -> m Text
attr Text
"Path"
Text
userUserId <- Text -> m Text
attr Text
"UserId"
Text
userUserName <- Text -> m Text
attr Text
"UserName"
User -> m User
forall (m :: * -> *) a. Monad m => a -> m a
return User :: Text -> UTCTime -> Text -> Text -> Text -> User
User{UTCTime
Text
userUserName :: Text
userUserId :: Text
userPath :: Text
userCreateDate :: UTCTime
userArn :: Text
userUserName :: Text
userUserId :: Text
userPath :: Text
userCreateDate :: UTCTime
userArn :: Text
..}
where
attr :: Text -> m Text
attr Text
name = String -> [Text] -> m Text
forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force (String
"Missing " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
Text.unpack Text
name) ([Text] -> m Text) -> [Text] -> m Text
forall a b. (a -> b) -> a -> b
$
Cursor
cursor Cursor -> (Cursor -> [Text]) -> [Text]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
name
data Group
= Group {
Group -> Text
groupArn :: Text
, Group -> UTCTime
groupCreateDate :: UTCTime
, Group -> Text
groupPath :: Text
, Group -> Text
groupGroupId :: Text
, Group -> Text
groupGroupName :: Text
}
deriving (Group -> Group -> Bool
(Group -> Group -> Bool) -> (Group -> Group -> Bool) -> Eq Group
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Group -> Group -> Bool
$c/= :: Group -> Group -> Bool
== :: Group -> Group -> Bool
$c== :: Group -> Group -> Bool
Eq, Eq Group
Eq Group
-> (Group -> Group -> Ordering)
-> (Group -> Group -> Bool)
-> (Group -> Group -> Bool)
-> (Group -> Group -> Bool)
-> (Group -> Group -> Bool)
-> (Group -> Group -> Group)
-> (Group -> Group -> Group)
-> Ord Group
Group -> Group -> Bool
Group -> Group -> Ordering
Group -> Group -> Group
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Group -> Group -> Group
$cmin :: Group -> Group -> Group
max :: Group -> Group -> Group
$cmax :: Group -> Group -> Group
>= :: Group -> Group -> Bool
$c>= :: Group -> Group -> Bool
> :: Group -> Group -> Bool
$c> :: Group -> Group -> Bool
<= :: Group -> Group -> Bool
$c<= :: Group -> Group -> Bool
< :: Group -> Group -> Bool
$c< :: Group -> Group -> Bool
compare :: Group -> Group -> Ordering
$ccompare :: Group -> Group -> Ordering
$cp1Ord :: Eq Group
Ord, Int -> Group -> ShowS
[Group] -> ShowS
Group -> String
(Int -> Group -> ShowS)
-> (Group -> String) -> ([Group] -> ShowS) -> Show Group
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Group] -> ShowS
$cshowList :: [Group] -> ShowS
show :: Group -> String
$cshow :: Group -> String
showsPrec :: Int -> Group -> ShowS
$cshowsPrec :: Int -> Group -> ShowS
Show, Typeable)
parseGroup :: MonadThrow m => Cu.Cursor -> m Group
parseGroup :: Cursor -> m Group
parseGroup Cursor
cursor = do
Text
groupArn <- Text -> m Text
attr Text
"Arn"
UTCTime
groupCreateDate <- Text -> m Text
attr Text
"CreateDate" m Text -> (Text -> m UTCTime) -> m UTCTime
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> m UTCTime
forall (m :: * -> *). MonadThrow m => String -> m UTCTime
parseDateTime (String -> m UTCTime) -> (Text -> String) -> Text -> m UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack
Text
groupPath <- Text -> m Text
attr Text
"Path"
Text
groupGroupId <- Text -> m Text
attr Text
"GroupId"
Text
groupGroupName <- Text -> m Text
attr Text
"GroupName"
Group -> m Group
forall (m :: * -> *) a. Monad m => a -> m a
return Group :: Text -> UTCTime -> Text -> Text -> Text -> Group
Group{UTCTime
Text
groupGroupName :: Text
groupGroupId :: Text
groupPath :: Text
groupCreateDate :: UTCTime
groupArn :: Text
groupGroupName :: Text
groupGroupId :: Text
groupPath :: Text
groupCreateDate :: UTCTime
groupArn :: Text
..}
where
attr :: Text -> m Text
attr Text
name = String -> [Text] -> m Text
forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force (String
"Missing " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
Text.unpack Text
name) ([Text] -> m Text) -> [Text] -> m Text
forall a b. (a -> b) -> a -> b
$
Cursor
cursor Cursor -> (Cursor -> [Text]) -> [Text]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
name
data AccessKeyStatus = AccessKeyActive | AccessKeyInactive
deriving (AccessKeyStatus -> AccessKeyStatus -> Bool
(AccessKeyStatus -> AccessKeyStatus -> Bool)
-> (AccessKeyStatus -> AccessKeyStatus -> Bool)
-> Eq AccessKeyStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c/= :: AccessKeyStatus -> AccessKeyStatus -> Bool
== :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c== :: AccessKeyStatus -> AccessKeyStatus -> Bool
Eq, Eq AccessKeyStatus
Eq AccessKeyStatus
-> (AccessKeyStatus -> AccessKeyStatus -> Ordering)
-> (AccessKeyStatus -> AccessKeyStatus -> Bool)
-> (AccessKeyStatus -> AccessKeyStatus -> Bool)
-> (AccessKeyStatus -> AccessKeyStatus -> Bool)
-> (AccessKeyStatus -> AccessKeyStatus -> Bool)
-> (AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus)
-> (AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus)
-> Ord AccessKeyStatus
AccessKeyStatus -> AccessKeyStatus -> Bool
AccessKeyStatus -> AccessKeyStatus -> Ordering
AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
$cmin :: AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
max :: AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
$cmax :: AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
>= :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c>= :: AccessKeyStatus -> AccessKeyStatus -> Bool
> :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c> :: AccessKeyStatus -> AccessKeyStatus -> Bool
<= :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c<= :: AccessKeyStatus -> AccessKeyStatus -> Bool
< :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c< :: AccessKeyStatus -> AccessKeyStatus -> Bool
compare :: AccessKeyStatus -> AccessKeyStatus -> Ordering
$ccompare :: AccessKeyStatus -> AccessKeyStatus -> Ordering
$cp1Ord :: Eq AccessKeyStatus
Ord, Int -> AccessKeyStatus -> ShowS
[AccessKeyStatus] -> ShowS
AccessKeyStatus -> String
(Int -> AccessKeyStatus -> ShowS)
-> (AccessKeyStatus -> String)
-> ([AccessKeyStatus] -> ShowS)
-> Show AccessKeyStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AccessKeyStatus] -> ShowS
$cshowList :: [AccessKeyStatus] -> ShowS
show :: AccessKeyStatus -> String
$cshow :: AccessKeyStatus -> String
showsPrec :: Int -> AccessKeyStatus -> ShowS
$cshowsPrec :: Int -> AccessKeyStatus -> ShowS
Show, Typeable)
data MfaDevice = MfaDevice
{ MfaDevice -> UTCTime
mfaEnableDate :: UTCTime
, MfaDevice -> Text
mfaSerialNumber :: Text
, MfaDevice -> Text
mfaUserName :: Text
} deriving (MfaDevice -> MfaDevice -> Bool
(MfaDevice -> MfaDevice -> Bool)
-> (MfaDevice -> MfaDevice -> Bool) -> Eq MfaDevice
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MfaDevice -> MfaDevice -> Bool
$c/= :: MfaDevice -> MfaDevice -> Bool
== :: MfaDevice -> MfaDevice -> Bool
$c== :: MfaDevice -> MfaDevice -> Bool
Eq, Eq MfaDevice
Eq MfaDevice
-> (MfaDevice -> MfaDevice -> Ordering)
-> (MfaDevice -> MfaDevice -> Bool)
-> (MfaDevice -> MfaDevice -> Bool)
-> (MfaDevice -> MfaDevice -> Bool)
-> (MfaDevice -> MfaDevice -> Bool)
-> (MfaDevice -> MfaDevice -> MfaDevice)
-> (MfaDevice -> MfaDevice -> MfaDevice)
-> Ord MfaDevice
MfaDevice -> MfaDevice -> Bool
MfaDevice -> MfaDevice -> Ordering
MfaDevice -> MfaDevice -> MfaDevice
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MfaDevice -> MfaDevice -> MfaDevice
$cmin :: MfaDevice -> MfaDevice -> MfaDevice
max :: MfaDevice -> MfaDevice -> MfaDevice
$cmax :: MfaDevice -> MfaDevice -> MfaDevice
>= :: MfaDevice -> MfaDevice -> Bool
$c>= :: MfaDevice -> MfaDevice -> Bool
> :: MfaDevice -> MfaDevice -> Bool
$c> :: MfaDevice -> MfaDevice -> Bool
<= :: MfaDevice -> MfaDevice -> Bool
$c<= :: MfaDevice -> MfaDevice -> Bool
< :: MfaDevice -> MfaDevice -> Bool
$c< :: MfaDevice -> MfaDevice -> Bool
compare :: MfaDevice -> MfaDevice -> Ordering
$ccompare :: MfaDevice -> MfaDevice -> Ordering
$cp1Ord :: Eq MfaDevice
Ord, Int -> MfaDevice -> ShowS
[MfaDevice] -> ShowS
MfaDevice -> String
(Int -> MfaDevice -> ShowS)
-> (MfaDevice -> String)
-> ([MfaDevice] -> ShowS)
-> Show MfaDevice
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MfaDevice] -> ShowS
$cshowList :: [MfaDevice] -> ShowS
show :: MfaDevice -> String
$cshow :: MfaDevice -> String
showsPrec :: Int -> MfaDevice -> ShowS
$cshowsPrec :: Int -> MfaDevice -> ShowS
Show, Typeable)
parseMfaDevice :: MonadThrow m => Cu.Cursor -> m MfaDevice
parseMfaDevice :: Cursor -> m MfaDevice
parseMfaDevice Cursor
cursor = do
UTCTime
mfaEnableDate <- Text -> m Text
attr Text
"EnableDate" m Text -> (Text -> m UTCTime) -> m UTCTime
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> m UTCTime
forall (m :: * -> *). MonadThrow m => String -> m UTCTime
parseDateTime (String -> m UTCTime) -> (Text -> String) -> Text -> m UTCTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack
Text
mfaSerialNumber <- Text -> m Text
attr Text
"SerialNumber"
Text
mfaUserName <- Text -> m Text
attr Text
"UserName"
MfaDevice -> m MfaDevice
forall (m :: * -> *) a. Monad m => a -> m a
return MfaDevice :: UTCTime -> Text -> Text -> MfaDevice
MfaDevice{UTCTime
Text
mfaUserName :: Text
mfaSerialNumber :: Text
mfaEnableDate :: UTCTime
mfaUserName :: Text
mfaSerialNumber :: Text
mfaEnableDate :: UTCTime
..}
where attr :: Text -> m Text
attr Text
name = String -> [Text] -> m Text
forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force (String
"Missing " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
Text.unpack Text
name) ([Text] -> m Text) -> [Text] -> m Text
forall a b. (a -> b) -> a -> b
$
Cursor
cursor Cursor -> (Cursor -> [Text]) -> [Text]
forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
name