aws 0.8.2 → 0.8.3
raw patch · 19 files changed
+1123/−3 lines, 19 filesdep ~basedep ~cryptohash
Dependency ranges changed: base, cryptohash
Files
- Aws/Iam.hs +7/−0
- Aws/Iam/Commands.hs +29/−0
- Aws/Iam/Commands/CreateAccessKey.hs +84/−0
- Aws/Iam/Commands/CreateUser.hs +51/−0
- Aws/Iam/Commands/DeleteAccessKey.hs +48/−0
- Aws/Iam/Commands/DeleteUser.hs +36/−0
- Aws/Iam/Commands/DeleteUserPolicy.hs +46/−0
- Aws/Iam/Commands/GetUser.hs +43/−0
- Aws/Iam/Commands/GetUserPolicy.hs +71/−0
- Aws/Iam/Commands/ListAccessKeys.hs +104/−0
- Aws/Iam/Commands/ListUserPolicies.hs +71/−0
- Aws/Iam/Commands/ListUsers.hs +75/−0
- Aws/Iam/Commands/PutUserPolicy.hs +51/−0
- Aws/Iam/Commands/UpdateAccessKey.hs +57/−0
- Aws/Iam/Commands/UpdateUser.hs +52/−0
- Aws/Iam/Core.hs +197/−0
- Aws/Iam/Internal.hs +76/−0
- README.org +5/−0
- aws.cabal +20/−3
+ Aws/Iam.hs view
@@ -0,0 +1,7 @@+module Aws.Iam+ ( module Aws.Iam.Commands+ , module Aws.Iam.Core+ ) where++import Aws.Iam.Commands+import Aws.Iam.Core
+ Aws/Iam/Commands.hs view
@@ -0,0 +1,29 @@+module Aws.Iam.Commands+ ( module Aws.Iam.Commands.CreateAccessKey+ , module Aws.Iam.Commands.CreateUser+ , module Aws.Iam.Commands.DeleteAccessKey+ , module Aws.Iam.Commands.DeleteUser+ , module Aws.Iam.Commands.DeleteUserPolicy+ , module Aws.Iam.Commands.GetUser+ , module Aws.Iam.Commands.GetUserPolicy+ , module Aws.Iam.Commands.ListAccessKeys+ , module Aws.Iam.Commands.ListUserPolicies+ , module Aws.Iam.Commands.ListUsers+ , module Aws.Iam.Commands.PutUserPolicy+ , module Aws.Iam.Commands.UpdateAccessKey+ , module Aws.Iam.Commands.UpdateUser+ ) where++import Aws.Iam.Commands.CreateAccessKey+import Aws.Iam.Commands.CreateUser+import Aws.Iam.Commands.DeleteAccessKey+import Aws.Iam.Commands.DeleteUser+import Aws.Iam.Commands.DeleteUserPolicy+import Aws.Iam.Commands.GetUser+import Aws.Iam.Commands.GetUserPolicy+import Aws.Iam.Commands.ListAccessKeys+import Aws.Iam.Commands.ListUserPolicies+import Aws.Iam.Commands.ListUsers+import Aws.Iam.Commands.PutUserPolicy+import Aws.Iam.Commands.UpdateAccessKey+import Aws.Iam.Commands.UpdateUser
+ Aws/Iam/Commands/CreateAccessKey.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.CreateAccessKey+ ( CreateAccessKey(..)+ , CreateAccessKeyResponse(..)+ , AccessKey(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Control.Applicative+import Data.Text (Text)+import qualified Data.Text as Text+import Data.Time+import Data.Typeable+import Text.XML.Cursor (($//))++-- | Creates a new AWS secret access key and corresponding AWS access key ID+-- for the given user name.+--+-- If a user name is not provided, IAM will determine the user name based on+-- the access key signing the request.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html>+data CreateAccessKey = CreateAccessKey (Maybe Text)+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery CreateAccessKey where+ type ServiceConfiguration CreateAccessKey = IamConfiguration+ signQuery (CreateAccessKey user)+ = iamAction' "CreateAccessKey" [("UserName",) <$> user]++-- | Represents the IAM @AccessKey@ data type.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_AccessKey.html>+data AccessKey+ = AccessKey {+ akAccessKeyId :: Text+ -- ^ The Access Key ID.+ , akCreateDate :: Maybe UTCTime+ -- ^ Date and time at which the access key was created.+ , akSecretAccessKey :: Text+ -- ^ Secret key used to sign requests. The secret key is accessible only+ -- during key creation.+ , akStatus :: AccessKeyStatus+ -- ^ Whether the access key is active or not.+ , akUserName :: Text+ -- ^ The user name for which this key is defined.+ }+ deriving (Eq, Ord, Show, Typeable)++data CreateAccessKeyResponse+ = CreateAccessKeyResponse AccessKey+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer CreateAccessKey CreateAccessKeyResponse where+ type ResponseMetadata CreateAccessKeyResponse = IamMetadata+ responseConsumer _+ = iamResponseConsumer $ \cursor -> do+ let attr name = force ("Missing " ++ Text.unpack name) $+ cursor $// elContent name+ akAccessKeyId <- attr "AccessKeyId"+ akSecretAccessKey <- attr "SecretAccessKey"+ akStatus <- readAccessKeyStatus <$> attr "Status"+ akUserName <- attr "UserName"+ akCreateDate <- readDate cursor+ return $ CreateAccessKeyResponse AccessKey{..}+ where+ readDate c = case c $// elCont "CreateDate" of+ (x:_) -> Just <$> parseDateTime x+ _ -> return Nothing+ readAccessKeyStatus s+ | Text.toCaseFold s == "Active" = AccessKeyActive+ | otherwise = AccessKeyInactive+++instance Transaction CreateAccessKey CreateAccessKeyResponse++instance AsMemoryResponse CreateAccessKeyResponse where+ type MemoryResponse CreateAccessKeyResponse = CreateAccessKeyResponse+ loadToMemory = return
+ Aws/Iam/Commands/CreateUser.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.CreateUser+ ( CreateUser(..)+ , CreateUserResponse(..)+ , User(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Control.Applicative+import Data.Text (Text)+import Data.Typeable++-- | Creates a new user.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateUser.html>+data CreateUser+ = CreateUser {+ cuUserName :: Text+ -- ^ Name of the new user+ , cuPath :: Maybe Text+ -- ^ Path under which the user will be created. Defaults to @/@ if+ -- omitted.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery CreateUser where+ type ServiceConfiguration CreateUser = IamConfiguration+ signQuery CreateUser{..}+ = iamAction' "CreateUser" [+ Just ("UserName", cuUserName)+ , ("Path",) <$> cuPath+ ]++data CreateUserResponse = CreateUserResponse User+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer CreateUser CreateUserResponse where+ type ResponseMetadata CreateUserResponse = IamMetadata+ responseConsumer _ = iamResponseConsumer $+ fmap CreateUserResponse . parseUser++instance Transaction CreateUser CreateUserResponse++instance AsMemoryResponse CreateUserResponse where+ type MemoryResponse CreateUserResponse = CreateUserResponse+ loadToMemory = return
+ Aws/Iam/Commands/DeleteAccessKey.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.DeleteAccessKey+ ( DeleteAccessKey(..)+ , DeleteAccessKeyResponse(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Control.Applicative+import Data.Text (Text)+import Data.Typeable++-- | Deletes the access key associated with the specified user.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteAccessKey.html>+data DeleteAccessKey+ = DeleteAccessKey {+ dakAccessKeyId :: Text+ -- ^ ID of the access key to be deleted.+ , dakUserName :: Maybe Text+ -- ^ User name with which the access key is associated.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery DeleteAccessKey where+ type ServiceConfiguration DeleteAccessKey = IamConfiguration+ signQuery DeleteAccessKey{..}+ = iamAction' "DeleteAccessKey" [+ Just ("AccessKeyId", dakAccessKeyId)+ , ("UserName",) <$> dakUserName+ ]++data DeleteAccessKeyResponse = DeleteAccessKeyResponse+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer DeleteAccessKey DeleteAccessKeyResponse where+ type ResponseMetadata DeleteAccessKeyResponse = IamMetadata+ responseConsumer _ = iamResponseConsumer (const $ return DeleteAccessKeyResponse)++instance Transaction DeleteAccessKey DeleteAccessKeyResponse++instance AsMemoryResponse DeleteAccessKeyResponse where+ type MemoryResponse DeleteAccessKeyResponse = DeleteAccessKeyResponse+ loadToMemory = return
+ Aws/Iam/Commands/DeleteUser.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.DeleteUser+ ( DeleteUser(..)+ , DeleteUserResponse(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Data.Text (Text)+import Data.Typeable++-- | Deletes the specified user.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteUser.html>+data DeleteUser = DeleteUser Text+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery DeleteUser where+ type ServiceConfiguration DeleteUser = IamConfiguration+ signQuery (DeleteUser userName)+ = iamAction "DeleteUser" [("UserName", userName)]++data DeleteUserResponse = DeleteUserResponse+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer DeleteUser DeleteUserResponse where+ type ResponseMetadata DeleteUserResponse = IamMetadata+ responseConsumer _ = iamResponseConsumer (const $ return DeleteUserResponse)++instance Transaction DeleteUser DeleteUserResponse++instance AsMemoryResponse DeleteUserResponse where+ type MemoryResponse DeleteUserResponse = DeleteUserResponse+ loadToMemory = return
+ Aws/Iam/Commands/DeleteUserPolicy.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.DeleteUserPolicy+ ( DeleteUserPolicy(..)+ , DeleteUserPolicyResponse(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Data.Text (Text)+import Data.Typeable++-- | Deletes the specified policy associated with the specified user.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteUserPolicy.html>+data DeleteUserPolicy+ = DeleteUserPolicy {+ dupPolicyName :: Text+ -- ^ Name of the policy to be deleted.+ , dupUserName :: Text+ -- ^ Name of the user with whom the policy is associated.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery DeleteUserPolicy where+ type ServiceConfiguration DeleteUserPolicy = IamConfiguration+ signQuery DeleteUserPolicy{..}+ = iamAction "DeleteUserPolicy" [+ ("PolicyName", dupPolicyName)+ , ("UserName", dupUserName)+ ]++data DeleteUserPolicyResponse = DeleteUserPolicyResponse+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer DeleteUserPolicy DeleteUserPolicyResponse where+ type ResponseMetadata DeleteUserPolicyResponse = IamMetadata+ responseConsumer _ = iamResponseConsumer (const $ return DeleteUserPolicyResponse)++instance Transaction DeleteUserPolicy DeleteUserPolicyResponse++instance AsMemoryResponse DeleteUserPolicyResponse where+ type MemoryResponse DeleteUserPolicyResponse = DeleteUserPolicyResponse+ loadToMemory = return
+ Aws/Iam/Commands/GetUser.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.GetUser+ ( GetUser(..)+ , GetUserResponse(..)+ , User(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Control.Applicative+import Data.Text (Text)+import Data.Typeable++-- | Retreives information about the given user.+--+-- If a user name is not given, IAM determines the user name based on the+-- access key signing the request.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_GetUser.html>+data GetUser = GetUser (Maybe Text)+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery GetUser where+ type ServiceConfiguration GetUser = IamConfiguration+ signQuery (GetUser user)+ = iamAction' "GetUser" [("UserName",) <$> user]++data GetUserResponse = GetUserResponse User+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer GetUser GetUserResponse where+ type ResponseMetadata GetUserResponse = IamMetadata+ responseConsumer _ = iamResponseConsumer $+ fmap GetUserResponse . parseUser++instance Transaction GetUser GetUserResponse++instance AsMemoryResponse GetUserResponse where+ type MemoryResponse GetUserResponse = GetUserResponse+ loadToMemory = return
+ Aws/Iam/Commands/GetUserPolicy.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.GetUserPolicy+ ( GetUserPolicy(..)+ , GetUserPolicyResponse(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Control.Applicative+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import Data.Typeable+import qualified Network.HTTP.Types as HTTP+import Text.XML.Cursor (($//))++-- | Retreives the specified policy document for the specified user.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_GetUserPolicy.html>+data GetUserPolicy+ = GetUserPolicy {+ gupPolicyName :: Text+ -- ^ Name of the policy.+ , gupUserName :: Text+ -- ^ Name of the user with whom the policy is associated.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery GetUserPolicy where+ type ServiceConfiguration GetUserPolicy = IamConfiguration+ signQuery GetUserPolicy{..}+ = iamAction "GetUserPolicy" [+ ("PolicyName", gupPolicyName)+ , ("UserName", gupUserName)+ ]++data GetUserPolicyResponse+ = GetUserPolicyResponse {+ guprPolicyDocument :: Text+ -- ^ The policy document.+ , guprPolicyName :: Text+ -- ^ Name of the policy.+ , guprUserName :: Text+ -- ^ Name of the user with whom the policy is associated.+ }+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer GetUserPolicy GetUserPolicyResponse where+ type ResponseMetadata GetUserPolicyResponse = IamMetadata+ responseConsumer _+ = iamResponseConsumer $ \cursor -> do+ let attr name = force ("Missing " ++ Text.unpack name) $+ cursor $// elContent name+ guprPolicyDocument <- decodePolicy <$>+ attr "PolicyDocument"+ guprPolicyName <- attr "PolicyName"+ guprUserName <- attr "UserName"+ return GetUserPolicyResponse{..}+ where+ decodePolicy = Text.decodeUtf8 . HTTP.urlDecode False+ . Text.encodeUtf8+++instance Transaction GetUserPolicy GetUserPolicyResponse++instance AsMemoryResponse GetUserPolicyResponse where+ type MemoryResponse GetUserPolicyResponse = GetUserPolicyResponse+ loadToMemory = return
+ Aws/Iam/Commands/ListAccessKeys.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.ListAccessKeys+ ( ListAccessKeys(..)+ , ListAccessKeysResponse(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Control.Applicative+import Data.Text (Text)+import Data.Time+import Data.Typeable+import Text.XML.Cursor (laxElement, ($/), ($//), (&|))++-- | Returns the access keys associated with the specified user.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAccessKeys.html>+data ListAccessKeys+ = ListAccessKeys {+ lakUserName :: Maybe Text+ -- ^ Name of the user. If the user name is not specified, IAM will+ -- determine the user based on the key sigining the request.+ , lakMarker :: Maybe Text+ -- ^ Used for paginating requests. Marks the position of the last+ -- request.+ , lakMaxItems :: Maybe Integer+ -- ^ Used for paginating requests. Specifies the maximum number of items+ -- to return in the response. Defaults to 100.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery ListAccessKeys where+ type ServiceConfiguration ListAccessKeys = IamConfiguration+ signQuery ListAccessKeys{..}+ = iamAction' "ListAccessKeys" $ [+ ("UserName",) <$> lakUserName+ ] <> markedIter lakMarker lakMaxItems++-- | Represents the IAM @AccessKeyMetadata@ data type.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_AccessKeyMetadata.html>+data AccessKeyMetadata+ = AccessKeyMetadata {+ akmAccessKeyId :: Maybe Text+ -- ^ ID of the access key.+ , akmCreateDate :: Maybe UTCTime+ -- ^ Date and time at which the access key was created.+ , akmStatus :: Maybe Text+ -- ^ Whether the access key is active.+ , akmUserName :: Maybe Text+ -- ^ Name of the user with whom the access key is associated.+ }+ deriving (Eq, Ord, Show, Typeable)++data ListAccessKeysResponse+ = ListAccessKeysResponse {+ lakrAccessKeyMetadata :: [AccessKeyMetadata]+ -- ^ List of 'AccessKeyMetadata' objects+ , lakrIsTruncated :: Bool+ -- ^ @True@ if the request was truncated because of too many items.+ , lakrMarker :: Maybe Text+ -- ^ Marks the position at which the request was truncated. This value+ -- must be passed with the next request to continue listing from the+ -- last position.+ }+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer ListAccessKeys ListAccessKeysResponse where+ type ResponseMetadata ListAccessKeysResponse = IamMetadata+ responseConsumer _+ = iamResponseConsumer $ \cursor -> do+ (lakrIsTruncated, lakrMarker) <- markedIterResponse cursor+ lakrAccessKeyMetadata <- sequence $+ cursor $// laxElement "member" &| buildAKM+ return ListAccessKeysResponse{..}+ where+ buildAKM m = do+ let mattr name = mhead $ m $/ elContent name+ let akmAccessKeyId = mattr "AccessKeyId"+ akmStatus = mattr "Status"+ akmUserName = mattr "UserName"+ akmCreateDate <- case m $/ elCont "CreateDate" of+ (x:_) -> Just <$> parseDateTime x+ _ -> return Nothing+ return AccessKeyMetadata{..}++ mhead (x:_) = Just x+ mhead _ = Nothing++instance Transaction ListAccessKeys ListAccessKeysResponse++instance IteratedTransaction ListAccessKeys ListAccessKeysResponse where+ nextIteratedRequest request response+ = case lakrMarker response of+ Nothing -> Nothing+ Just marker -> Just $ request { lakMarker = Just marker }++instance AsMemoryResponse ListAccessKeysResponse where+ type MemoryResponse ListAccessKeysResponse = ListAccessKeysResponse+ loadToMemory = return
+ Aws/Iam/Commands/ListUserPolicies.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.ListUserPolicies+ ( ListUserPolicies(..)+ , ListUserPoliciesResponse(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Data.Text (Text)+import Data.Typeable+import Text.XML.Cursor (content, laxElement, ($//), (&/))++-- | Lists the user policies associated with the specified user.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_ListUserPolicies.html>+data ListUserPolicies+ = ListUserPolicies {+ lupUserName :: Text+ -- ^ Policies associated with this user will be listed.+ , lupMarker :: Maybe Text+ -- ^ Used for paginating requests. Marks the position of the last+ -- request.+ , lupMaxItems :: Maybe Integer+ -- ^ Used for paginating requests. Specifies the maximum number of items+ -- to return in the response. Defaults to 100.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery ListUserPolicies where+ type ServiceConfiguration ListUserPolicies = IamConfiguration+ signQuery ListUserPolicies{..}+ = iamAction' "ListUserPolicies" $ [+ Just ("UserName", lupUserName)+ ] <> markedIter lupMarker lupMaxItems++data ListUserPoliciesResponse+ = ListUserPoliciesResponse {+ luprPolicyNames :: [Text]+ -- ^ List of policy names.+ , luprIsTruncated :: Bool+ -- ^ @True@ if the request was truncated because of too many items.+ , luprMarker :: Maybe Text+ -- ^ Marks the position at which the request was truncated. This value+ -- must be passed with the next request to continue listing from the+ -- last position.+ }+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer ListUserPolicies ListUserPoliciesResponse where+ type ResponseMetadata ListUserPoliciesResponse = IamMetadata+ responseConsumer _+ = iamResponseConsumer $ \cursor -> do+ (luprIsTruncated, luprMarker) <- markedIterResponse cursor+ let luprPolicyNames = cursor $// laxElement "member" &/ content+ return ListUserPoliciesResponse{..}++instance Transaction ListUserPolicies ListUserPoliciesResponse++instance IteratedTransaction ListUserPolicies ListUserPoliciesResponse where+ nextIteratedRequest request response+ = case luprMarker response of+ Nothing -> Nothing+ Just marker -> Just $ request { lupMarker = Just marker }++instance AsMemoryResponse ListUserPoliciesResponse where+ type MemoryResponse ListUserPoliciesResponse = ListUserPoliciesResponse+ loadToMemory = return
+ Aws/Iam/Commands/ListUsers.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.ListUsers+ ( ListUsers(..)+ , ListUsersResponse(..)+ , User(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Control.Applicative+import Data.Text (Text)+import Data.Typeable+import Text.XML.Cursor (laxElement, ($//), (&|))++-- | Lists users that have the specified path prefix.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_ListUsers.html>+data ListUsers+ = ListUsers {+ luPathPrefix :: Maybe Text+ -- ^ Users defined under this path will be listed. If omitted, defaults+ -- to @/@, which lists all users.+ , luMarker :: Maybe Text+ -- ^ Used for paginating requests. Marks the position of the last+ -- request.+ , luMaxItems :: Maybe Integer+ -- ^ Used for paginating requests. Specifies the maximum number of items+ -- to return in the response. Defaults to 100.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery ListUsers where+ type ServiceConfiguration ListUsers = IamConfiguration+ signQuery ListUsers{..}+ = iamAction' "ListUsers" $ [+ ("PathPrefix",) <$> luPathPrefix+ ] <> markedIter luMarker luMaxItems++data ListUsersResponse+ = ListUsersResponse {+ lurUsers :: [User]+ -- ^ List of 'User's.+ , lurIsTruncated :: Bool+ -- ^ @True@ if the request was truncated because of too many items.+ , lurMarker :: Maybe Text+ -- ^ Marks the position at which the request was truncated. This value+ -- must be passed with the next request to continue listing from the+ -- last position.+ }+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer ListUsers ListUsersResponse where+ type ResponseMetadata ListUsersResponse = IamMetadata+ responseConsumer _+ = iamResponseConsumer $ \cursor -> do+ (lurIsTruncated, lurMarker) <- markedIterResponse cursor+ lurUsers <- sequence $+ cursor $// laxElement "member" &| parseUser+ return ListUsersResponse{..}++instance Transaction ListUsers ListUsersResponse++instance IteratedTransaction ListUsers ListUsersResponse where+ nextIteratedRequest request response+ = case lurMarker response of+ Nothing -> Nothing+ Just marker -> Just $ request { luMarker = Just marker }++instance AsMemoryResponse ListUsersResponse where+ type MemoryResponse ListUsersResponse = ListUsersResponse+ loadToMemory = return
+ Aws/Iam/Commands/PutUserPolicy.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.PutUserPolicy+ ( PutUserPolicy(..)+ , PutUserPolicyResponse(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Data.Text (Text)+import Data.Typeable++-- | Adds a policy document with the specified name, associated with the+-- specified user.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_PutUserPolicy.html>+data PutUserPolicy+ = PutUserPolicy {+ pupPolicyDocument :: Text+ -- ^ The policy document.+ , pupPolicyName :: Text+ -- ^ Name of the policy.+ , pupUserName :: Text+ -- ^ Name of the user with whom this policy is associated.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery PutUserPolicy where+ type ServiceConfiguration PutUserPolicy = IamConfiguration+ signQuery PutUserPolicy{..}+ = iamAction "PutUserPolicy" [+ ("PolicyDocument", pupPolicyDocument)+ , ("PolicyName" , pupPolicyName)+ , ("UserName" , pupUserName)+ ]++data PutUserPolicyResponse = PutUserPolicyResponse+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer PutUserPolicy PutUserPolicyResponse where+ type ResponseMetadata PutUserPolicyResponse = IamMetadata+ responseConsumer _+ = iamResponseConsumer (const $ return PutUserPolicyResponse)++instance Transaction PutUserPolicy PutUserPolicyResponse++instance AsMemoryResponse PutUserPolicyResponse where+ type MemoryResponse PutUserPolicyResponse = PutUserPolicyResponse+ loadToMemory = return
+ Aws/Iam/Commands/UpdateAccessKey.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.UpdateAccessKey+ ( UpdateAccessKey(..)+ , UpdateAccessKeyResponse(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Control.Applicative+import Data.Text (Text)+import Data.Typeable++-- | Changes the status of the specified access key.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateAccessKey.html>+data UpdateAccessKey+ = UpdateAccessKey {+ uakAccessKeyId :: Text+ -- ^ ID of the access key to update.+ , uakStatus :: AccessKeyStatus+ -- ^ New status of the access key.+ , uakUserName :: Maybe Text+ -- ^ Name of the user to whom the access key belongs. If omitted, the+ -- user will be determined based on the access key used to sign the+ -- request.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery UpdateAccessKey where+ type ServiceConfiguration UpdateAccessKey = IamConfiguration+ signQuery UpdateAccessKey{..}+ = iamAction' "UpdateAccessKey" [+ Just ("AccessKeyId", uakAccessKeyId)+ , Just ("Status", showStatus uakStatus)+ , ("UserName",) <$> uakUserName+ ]+ where+ showStatus AccessKeyActive = "Active"+ showStatus _ = "Inactive"++data UpdateAccessKeyResponse = UpdateAccessKeyResponse+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer UpdateAccessKey UpdateAccessKeyResponse where+ type ResponseMetadata UpdateAccessKeyResponse = IamMetadata+ responseConsumer _+ = iamResponseConsumer (const $ return UpdateAccessKeyResponse)++instance Transaction UpdateAccessKey UpdateAccessKeyResponse++instance AsMemoryResponse UpdateAccessKeyResponse where+ type MemoryResponse UpdateAccessKeyResponse = UpdateAccessKeyResponse+ loadToMemory = return
+ Aws/Iam/Commands/UpdateUser.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeFamilies #-}+module Aws.Iam.Commands.UpdateUser+ ( UpdateUser(..)+ , UpdateUserResponse(..)+ ) where++import Aws.Core+import Aws.Iam.Core+import Aws.Iam.Internal+import Control.Applicative+import Data.Text (Text)+import Data.Typeable++-- | Updates the name and/or path of the specified user.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateUser.html>+data UpdateUser+ = UpdateUser {+ uuUserName :: Text+ -- ^ Name of the user to be updated.+ , uuNewUserName :: Maybe Text+ -- ^ New name for the user.+ , uuNewPath :: Maybe Text+ -- ^ New path to which the user will be moved.+ }+ deriving (Eq, Ord, Show, Typeable)++instance SignQuery UpdateUser where+ type ServiceConfiguration UpdateUser = IamConfiguration+ signQuery UpdateUser{..}+ = iamAction' "UpdateUser" [+ Just ("UserName", uuUserName)+ , ("NewUserName",) <$> uuNewUserName+ , ("NewPath",) <$> uuNewPath+ ]++data UpdateUserResponse = UpdateUserResponse+ deriving (Eq, Ord, Show, Typeable)++instance ResponseConsumer UpdateUser UpdateUserResponse where+ type ResponseMetadata UpdateUserResponse = IamMetadata+ responseConsumer _+ = iamResponseConsumer (const $ return UpdateUserResponse)++instance Transaction UpdateUser UpdateUserResponse++instance AsMemoryResponse UpdateUserResponse where+ type MemoryResponse UpdateUserResponse = UpdateUserResponse+ loadToMemory = return
+ Aws/Iam/Core.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RecordWildCards #-}+module Aws.Iam.Core+ ( iamSignQuery+ , iamResponseConsumer+ , IamMetadata(..)+ , IamConfiguration(..)+ , IamError(..)++ , parseDateTime++ , AccessKeyStatus(..)+ , User(..)+ , parseUser+ ) where++import Aws.Core+import qualified Blaze.ByteString.Builder as Blaze+import qualified Blaze.ByteString.Builder.Char8 as Blaze8+import Control.Exception (Exception)+import qualified Control.Failure as F+import Control.Monad+import Data.ByteString (ByteString)+import Data.IORef+import Data.List (intersperse, sort)+import Data.Maybe+import Data.Monoid+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+import System.Locale+import Text.XML.Cursor (($//))+import qualified Text.XML.Cursor as Cu++data IamError+ = IamError {+ iamStatusCode :: HTTP.Status+ , iamErrorCode :: Text+ , iamErrorMessage :: Text+ }+ deriving (Show, Typeable)++instance Exception IamError++data IamMetadata+ = IamMetadata {+ requestId :: Maybe Text+ }+ deriving (Show, Typeable)++instance Loggable IamMetadata where+ toLogText (IamMetadata r) = "IAM: request ID=" <> fromMaybe "<none>" r++instance Monoid IamMetadata where+ mempty = IamMetadata Nothing+ IamMetadata r1 `mappend` IamMetadata r2 = IamMetadata (r1 `mplus` r2)++data IamConfiguration qt+ = IamConfiguration {+ iamEndpoint :: ByteString+ , iamPort :: Int+ , iamProtocol :: Protocol+ , iamHttpMethod :: Method+ }+ deriving (Show)++instance DefaultServiceConfiguration (IamConfiguration NormalQuery) where+ defServiceConfig = iam PostQuery HTTPS iamEndpointDefault+ debugServiceConfig = iam PostQuery HTTP iamEndpointDefault++instance DefaultServiceConfiguration (IamConfiguration UriOnlyQuery) where+ defServiceConfig = iam Get HTTPS iamEndpointDefault+ debugServiceConfig = iam Get HTTP iamEndpointDefault++-- | The default IAM endpoint.+iamEndpointDefault :: ByteString+iamEndpointDefault = "iam.amazonaws.com"++-- | Constructs an IamConfiguration with the specified parameters.+iam :: Method -> Protocol -> ByteString -> IamConfiguration qt+iam method protocol endpoint+ = IamConfiguration {+ iamEndpoint = endpoint+ , iamProtocol = protocol+ , iamPort = defaultPort protocol+ , iamHttpMethod = method+ }++-- | Constructs a 'SignedQuery' with the specified request parameters.+iamSignQuery+ :: [(ByteString, ByteString)]+ -- ^ Pairs of parameter names and values that will be passed as part of+ -- the request data.+ -> IamConfiguration qt+ -> SignatureData+ -> SignedQuery+iamSignQuery q IamConfiguration{..} SignatureData{..}+ = SignedQuery {+ sqMethod = iamHttpMethod+ , sqProtocol = iamProtocol+ , sqHost = iamEndpoint+ , sqPort = iamPort+ , sqPath = "/"+ , sqQuery = signedQuery+ , sqDate = Just signatureTime+ , sqAuthorization = Nothing+ , sqContentType = Nothing+ , sqContentMd5 = Nothing+ , sqAmzHeaders = []+ , sqOtherHeaders = []+ , sqBody = Nothing+ , sqStringToSign = stringToSign+ }+ where+ sig = signature signatureCredentials HmacSHA256 stringToSign+ signedQuery = ("Signature", Just sig):expandedQuery+ accessKey = accessKeyID signatureCredentials+ timestampHeader =+ case signatureTimeInfo of+ AbsoluteTimestamp time -> ("Timestamp", fmtAmzTime time)+ AbsoluteExpires time -> ("Expires" , fmtAmzTime time)+ newline = Blaze8.fromChar '\n'+ stringToSign = Blaze.toByteString . mconcat . intersperse newline $+ map Blaze.copyByteString+ [httpMethod iamHttpMethod, iamEndpoint, "/"]+ ++ [HTTP.renderQueryBuilder False expandedQuery]+ expandedQuery = HTTP.toQuery . sort $ (q ++) [+ ("AWSAccessKeyId" , accessKey)+ , ("SignatureMethod" , amzHash HmacSHA256)+ , ("SignatureVersion", "2")+ , ("Version" , "2010-05-08")+ , timestampHeader+ ]++-- | Reads the metadata from an IAM response and delegates parsing the rest of+-- the data from the response to the given function.+iamResponseConsumer :: (Cu.Cursor -> Response IamMetadata a)+ -> IORef IamMetadata+ -> HTTPResponseConsumer a+iamResponseConsumer inner md resp = xmlCursorConsumer parse md resp+ where+ parse cursor = do+ let rid = listToMaybe $ cursor $// elContent "RequestID"+ tellMetadata $ IamMetadata rid+ case cursor $// Cu.laxElement "Error" of+ [] -> inner cursor+ (err:_) -> fromError err+ fromError cursor = do+ errCode <- force "Missing Error Code" $ cursor $// elContent "Code"+ errMsg <- force "Missing Error Message" $ cursor $// elContent "Message"+ F.failure $ IamError (HTTP.responseStatus resp) errCode errMsg++-- | Parses IAM @DateTime@ data type.+parseDateTime :: (F.Failure XmlException m) => String -> m UTCTime+parseDateTime x+ = case parseTime defaultTimeLocale iso8601UtcDate x of+ Nothing -> F.failure $ XmlException $ "Invalid DateTime: " ++ x+ Just dt -> return dt++-- | The IAM @User@ data type.+--+-- <http://docs.aws.amazon.com/IAM/latest/APIReference/API_User.html>+data User+ = User {+ userArn :: Text+ -- ^ ARN used to refer to this user.+ , userCreateDate :: UTCTime+ -- ^ Date and time at which the user was created.+ , userPath :: Text+ -- ^ Path under which the user was created.+ , userUserId :: Text+ -- ^ Unique identifier used to refer to this user. + , userUserName :: Text+ -- ^ Name of the user.+ }+ deriving (Eq, Ord, Show, Typeable)++-- | Parses the IAM @User@ data type.+parseUser :: (F.Failure XmlException m) => Cu.Cursor -> m User+parseUser cursor = do+ userArn <- attr "Arn"+ userCreateDate <- attr "CreateDate" >>= parseDateTime . Text.unpack+ userPath <- attr "Path"+ userUserId <- attr "UserId"+ userUserName <- attr "UserName"+ return User{..}+ where+ attr name = force ("Missing " ++ Text.unpack name) $+ cursor $// elContent name+++data AccessKeyStatus = AccessKeyActive | AccessKeyInactive+ deriving (Eq, Ord, Show, Typeable)
+ Aws/Iam/Internal.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TupleSections #-}+module Aws.Iam.Internal+ ( iamAction+ , iamAction'+ , markedIter+ , markedIterResponse++ -- * Re-exports+ , (<>)+ ) where++import Aws.Core+import Aws.Iam.Core+import Control.Applicative+import Control.Arrow (second)+import qualified Control.Failure as F+import Control.Monad+import Data.ByteString (ByteString)+import Data.Maybe+import Data.Monoid ((<>))+import Data.Text (Text)+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import Text.XML.Cursor (($//))+import qualified Text.XML.Cursor as Cu++-- | Similar to 'iamSignQuery'. Accepts parameters in @Text@ form and UTF-8+-- encodes them. Accepts the @Action@ parameter separately since it's always+-- required.+iamAction+ :: ByteString+ -> [(ByteString, Text)]+ -> IamConfiguration qt+ -> SignatureData+ -> SignedQuery+iamAction action = iamSignQuery+ . (:) ("Action", action)+ . map (second Text.encodeUtf8)++-- | Similar to 'iamAction'. Accepts parameter list with @Maybe@ parameters.+-- Ignores @Nothing@s.+iamAction'+ :: ByteString+ -> [Maybe (ByteString, Text)]+ -> IamConfiguration qt+ -> SignatureData+ -> SignedQuery+iamAction' action = iamAction action . catMaybes++-- | Returns the parameters @Marker@ and @MaxItems@ that are present in all+-- IAM data pagination requests.+markedIter :: Maybe Text -> Maybe Integer -> [Maybe (ByteString, Text)]+markedIter marker maxItems+ = [ ("Marker" ,) <$> marker+ , ("MaxItems",) . encodeInteger <$> maxItems+ ]+ where+ encodeInteger = Text.pack . show++-- | Reads and returns the @IsTruncated@ and @Marker@ attributes present in+-- all IAM data pagination responses.+markedIterResponse+ :: F.Failure XmlException m+ => Cu.Cursor+ -> m (Bool, Maybe Text)+markedIterResponse cursor = do+ isTruncated <- (Text.toCaseFold "true" ==) `liftM` attr "IsTruncated"+ marker <- if isTruncated+ then Just `liftM` attr "Marker"+ else return Nothing+ return (isTruncated, marker)+ where+ attr name = force ("Missing " ++ Text.unpack name) $+ cursor $// elContent name
README.org view
@@ -90,6 +90,10 @@ ** 0.8 series +- 0.8.3+ - compatibility with cryptohash 0.11+ - experimental IAM support+ - 0.8.2 - compatibility with cereal 0.4.x @@ -199,6 +203,7 @@ | Name | Github | E-Mail | Company | Components | |--------------------+--------------+---------------------------+------------------------+---------------|+| Abhinav Gupta | [[https://github.com/abhinav][abhinav]] | mail@abhinavg.net | - | IAM, SES | | Aristid Breitkreuz | [[https://github.com/aristidb][aristidb]] | aristidb@gmail.com | - | Co-Maintainer | | Bas van Dijk | [[https://github.com/basvandijk][basvandijk]] | v.dijk.bas@gmail.com | [[http://erudify.ch][Erudify AG]] | S3 | | David Vollbracht | [[https://github.com/qxjit][qxjit]] | | | |
aws.cabal view
@@ -1,5 +1,5 @@ Name: aws-Version: 0.8.2+Version: 0.8.3 Synopsis: Amazon Web Services (AWS) for Haskell Description: Bindings for Amazon Web Services (AWS), with the aim of supporting all AWS services. To see a high level overview of the library, see the README at <https://github.com/aristidb/aws/blob/master/README.org>. Homepage: http://github.com/aristidb/aws@@ -20,7 +20,7 @@ Source-repository this type: git location: https://github.com/aristidb/aws.git- tag: 0.8.2+ tag: 0.8.3 Source-repository head type: git@@ -36,6 +36,23 @@ Aws.Aws, Aws.Core, Aws.Ec2.InstanceMetadata,+ Aws.Iam,+ Aws.Iam.Commands,+ Aws.Iam.Commands.CreateAccessKey,+ Aws.Iam.Commands.CreateUser,+ Aws.Iam.Commands.DeleteAccessKey,+ Aws.Iam.Commands.DeleteUser,+ Aws.Iam.Commands.DeleteUserPolicy,+ Aws.Iam.Commands.GetUser,+ Aws.Iam.Commands.GetUserPolicy,+ Aws.Iam.Commands.ListAccessKeys,+ Aws.Iam.Commands.ListUserPolicies,+ Aws.Iam.Commands.ListUsers,+ Aws.Iam.Commands.PutUserPolicy,+ Aws.Iam.Commands.UpdateAccessKey,+ Aws.Iam.Commands.UpdateUser,+ Aws.Iam.Core,+ Aws.Iam.Internal, Aws.S3, Aws.S3.Commands, Aws.S3.Commands.CopyObject,@@ -88,7 +105,7 @@ conduit >= 1.0 && < 1.1, containers >= 0.4, crypto-api >= 0.9,- cryptohash >= 0.8 && < 0.11,+ cryptohash >= 0.8 && < 0.12, cryptohash-cryptoapi == 0.1.*, directory >= 1.0 && < 1.3, failure >= 0.2.0.1 && < 0.3,