powerdns-0.4.4: PowerDNS/API/TSIGKeys.hs
-- |
-- Module: PowerDNS.API.TSIGKeys
-- Description: TSIGKeys endpoints for PowerDNS API
--
-- Implementation of the API endpoints described at [PowerDNS TSIGKeys API](https://doc.powerdns.com/authoritative/http-api/tsigkey.html)
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TemplateHaskell #-}
module PowerDNS.API.TSIGKeys
(
-- * API
TSIGKeysAPI(..)
-- * Data types
, TSIGKey(..)
, TSIGAlgorithm(..)
)
where
import qualified Control.Monad.Fail as Fail
import Data.Char (toLower)
import Data.Data (Data)
import Data.Functor ((<&>))
import Control.DeepSeq (NFData)
import Data.Aeson (FromJSON(..), ToJSON(..), Value(String),
object, withObject, (.:), (.:?), (.=))
import Data.Aeson.TH (allNullaryToStringTag, constructorTagModifier,
defaultOptions, deriveJSON)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Base64 as BS64
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Servant.API
import Servant.API.Generic
---------------------------------------------------------------------------------------
data TSIGKeysAPI f = TSIGKeysAPI
{ apiListTSIGKeys :: f :- Summary "List TSIG keys"
:> "servers" :> Capture "server_id" T.Text :> "tsigkeys"
:> Get '[JSON] [TSIGKey]
, apiCreateTSIGKey :: f :- Summary "Create TSIG key"
:> "servers" :> Capture "server_id" T.Text :> "tsigkeys"
:> ReqBody '[JSON] TSIGKey
:> PostCreated '[JSON] TSIGKey
, apiGetTSIGKey :: f :- Summary "Get TSIG key"
:> "servers" :> Capture "server_id" T.Text :> "tsigkeys" :> Capture "tsigkey_id" T.Text
:> Get '[JSON] TSIGKey
, apiUpdateTSIGKey :: f :- Summary "Update TSIG key"
:> "servers" :> Capture "server_id" T.Text :> "tsigkeys" :> Capture "tsigkey_id" T.Text
:> ReqBody '[JSON] TSIGKey
:> Put '[JSON] TSIGKey
, apiDeleteTSIGKey :: f :- Summary "DElete TSIG key"
:> "servers" :> Capture "server_id" T.Text :> "tsigkeys" :> Capture "tsigkey_id" T.Text
:> DeleteNoContent
} deriving Generic
----------------------------------------------------------------------------------------
data TSIGKey = TSIGKey
{ tsk_name :: T.Text
, tsk_id :: T.Text
, tsk_algorithm :: Maybe TSIGAlgorithm
, tsk_key :: Maybe BS.ByteString
-- ^ Unlike the original PowerDNS API we do not require the key to be base64 encoded.
} deriving (Eq, Ord, Read, Show, Generic, NFData, Data)
----------------------------------------------------------------------------------------
-- | Supported algorithms according to [PowerDNS TSIG Documentation](https://doc.powerdns.com/authoritative/tsig.html#tsig)
data TSIGAlgorithm = HMAC_MD5
| HMAC_SHA1
| HMAC_SHA224
| HMAC_SHA256
| HMAC_SHA384
| HMAC_SHA512
deriving (Eq, Ord, Read, Show, Generic, NFData, Data)
$(deriveJSON defaultOptions { allNullaryToStringTag = True
, constructorTagModifier = fmap $ \c ->
if c == '_' then '-' else toLower c
} ''TSIGAlgorithm)
----------------------------------------------------------------------------------------
instance ToJSON TSIGKey where
toJSON key = object [ "name" .= tsk_name key
, "id" .= tsk_id key
, "type" .= String "TSIGKey"
, "algorithm" .= tsk_algorithm key
, "key" .= (tsk_key key <&> encode64)
]
instance FromJSON TSIGKey where
parseJSON = withObject "TSIGKey" $ \o -> do
tsk_name <- o .: "name"
tsk_id <- o .: "id"
tsk_algorithm <- o .:? "algorithm"
tsk_key <- o .:? "key" >>= traverse decode64
pure TSIGKey{..}
encode64 :: BS.ByteString -> T.Text
encode64 = T.decodeUtf8 . BS64.encode
decode64 :: Fail.MonadFail m => T.Text -> m BS.ByteString
decode64 i = case BS64.decode (T.encodeUtf8 i) of
Left err -> Fail.fail err
Right k -> pure k