credentials-0.0.1.1: src/Credentials/Types.hs
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
-- |
-- Module : Credentials.Types
-- Copyright : (c) 2015-2016 Brendan Hay
-- License : Mozilla Public License, v. 2.0.
-- Maintainer : Brendan Hay <brendan.g.hay@gmail.com>
-- Stability : provisional
-- Portability : non-portable (GHC extensions)
--
module Credentials.Types where
import Control.Exception.Lens (exception)
import Control.Lens (Prism', prism)
import Control.Monad.Catch (Exception, SomeException)
import Crypto.Hash (SHA256)
import Crypto.MAC.HMAC (HMAC)
import Data.ByteString (ByteString)
import Data.HashMap.Strict (HashMap)
import Data.Text (Text)
import Data.Typeable (Typeable)
import Network.AWS.Data
-- | The KMS master key identifier.
newtype KeyId = KeyId Text
deriving (Eq, Ord, Show, FromText, ToText, ToByteString, ToLog)
-- | The default KMS master key alias.
--
-- /Value:/ @alias\/credentials@
defaultKeyId :: KeyId
defaultKeyId = KeyId "alias/credentials"
-- | A shared/readable name for a secret.
newtype Name = Name Text
deriving (Eq, Ord, Show, FromText, ToText, ToByteString, ToLog)
-- | An opaque, non-monotonic revision number.
newtype Revision = Revision ByteString
deriving (Eq, Ord, Show, FromText, ToText, ToByteString, ToLog)
-- | A KMS encryption context.
--
-- /See:/ KMS <http://docs.aws.amazon.com/kms/latest/developerguide/encrypt-context.html Encryption Context>
-- documentation for more information.
newtype Context = Context { fromContext :: HashMap Text Text }
deriving (Eq, Show, Monoid)
-- | The encryption parameters required to perform decryption.
data Encrypted = Encrypted
{ wrappedKey :: !ByteString -- ^ The wrapped (encrypted) data encryption key.
, ciphertext :: !ByteString -- ^ The encrypted ciphertext.
, digest :: !(HMAC SHA256) -- ^ HMAC SHA256 digest of the ciphertext.
}
-- | Denotes idempotency of an action. That is, whether an action resulted
-- in any setup being performed.
data Setup
= Created
| Exists
deriving (Eq, Show)
instance ToText Setup where
toText = \case
Created -> "created"
Exists -> "exists"
instance ToLog Setup where
build = build . toText
data CredentialError
= MasterKeyMissing KeyId (Maybe Text)
-- ^ The specified master key id doesn't exist.
| IntegrityFailure Name ByteString ByteString
-- ^ The computed HMAC doesn't matched the stored HMAC.
| EncryptFailure Context Name Text
-- ^ Failure occured during local encryption.
| DecryptFailure Context Name Text
-- ^ Failure occured during local decryption.
| StorageMissing Text
-- ^ Storage doesn't exist, or has gone on holiday.
| StorageFailure Text
-- ^ Some storage pre-condition wasn't met.
-- For example: DynamoDB column size exceeded.
| FieldMissing Text [Text]
-- ^ Missing field from the storage engine.
| FieldInvalid Text String
-- ^ Unable to parse field from the storage engine.
| SecretMissing Name (Maybe Revision) Text
-- ^ Secret with the specified name cannot found.
| OptimisticLockFailure Name Revision Text
-- ^ Attempting to insert a revision that already exists.
deriving (Eq, Show, Typeable)
instance Exception CredentialError
class AsCredentialError a where
_CredentialError :: Prism' a CredentialError
_MasterKeyMissing :: Prism' a (KeyId, Maybe Text)
_IntegrityFailure :: Prism' a (Name, ByteString, ByteString)
_EncryptFailure :: Prism' a (Context, Name, Text)
_DecryptFailure :: Prism' a (Context, Name, Text)
_StorageMissing :: Prism' a Text
_StorageFailure :: Prism' a Text
_FieldMissing :: Prism' a (Text, [Text])
_FieldInvalid :: Prism' a (Text, String)
_SecretMissing :: Prism' a (Name, Maybe Revision, Text)
_OptimisticLockFailure :: Prism' a (Name, Revision, Text)
_MasterKeyMissing = (.) _CredentialError _MasterKeyMissing
_IntegrityFailure = (.) _CredentialError _IntegrityFailure
_EncryptFailure = (.) _CredentialError _EncryptFailure
_DecryptFailure = (.) _CredentialError _DecryptFailure
_StorageMissing = (.) _CredentialError _StorageMissing
_StorageFailure = (.) _CredentialError _StorageFailure
_FieldMissing = (.) _CredentialError _FieldMissing
_FieldInvalid = (.) _CredentialError _FieldInvalid
_SecretMissing = (.) _CredentialError _SecretMissing
_OptimisticLockFailure = (.) _CredentialError _OptimisticLockFailure
instance AsCredentialError CredentialError where
_CredentialError = id
_MasterKeyMissing = prism
(\(key, msg) -> MasterKeyMissing key msg)
(\case
MasterKeyMissing key msg -> Right (key, msg)
x -> Left x)
_IntegrityFailure = prism
(\(name, a, b) -> IntegrityFailure name a b)
(\case
IntegrityFailure name a b -> Right (name, a, b)
x -> Left x)
_EncryptFailure = prism
(\(ctx, name, msg) -> EncryptFailure ctx name msg)
(\case
EncryptFailure ctx name msg -> Right (ctx, name, msg)
x -> Left x)
_DecryptFailure = prism
(\(ctx, name, msg) -> DecryptFailure ctx name msg)
(\case
DecryptFailure ctx name msg -> Right (ctx, name, msg)
x -> Left x)
_StorageMissing = prism
StorageMissing
(\case
StorageMissing msg -> Right msg
x -> Left x)
_StorageFailure = prism
StorageFailure
(\case
StorageFailure msg -> Right msg
x -> Left x)
_FieldMissing = prism
(\(field, found) -> FieldMissing field found)
(\case
FieldMissing field found -> Right (field, found)
x -> Left x)
_FieldInvalid = prism
(\(field, msg) -> FieldInvalid field msg)
(\case
FieldInvalid field msg -> Right (field, msg)
x -> Left x)
_SecretMissing = prism
(\(name, rev, msg) -> SecretMissing name rev msg)
(\case
SecretMissing name rev msg -> Right (name, rev, msg)
x -> Left x)
_OptimisticLockFailure = prism
(\(name, rev, msg) -> OptimisticLockFailure name rev msg)
(\case
OptimisticLockFailure name rev msg -> Right (name, rev, msg)
x -> Left x)
instance AsCredentialError SomeException where
_CredentialError = exception