module Test.Ganeti.Confd.Utils (testConfd_Utils) where
import Test.QuickCheck
import qualified Text.JSON as J
import Test.Ganeti.TestHelper
import Test.Ganeti.TestCommon
import Test.Ganeti.Confd.Types ()
import qualified Ganeti.BasicTypes as BasicTypes
import qualified Ganeti.Confd.Types as Confd
import qualified Ganeti.Confd.Utils as Confd.Utils
import qualified Ganeti.Constants as C
import qualified Ganeti.Hash as Hash
prop_req_sign :: Hash.HashKey
-> NonNegative Integer
-> Positive Integer
-> Bool
-> Confd.ConfdRequest
-> Property
prop_req_sign key (NonNegative timestamp) (Positive bad_delta)
pm crq =
forAll (choose (0, fromIntegral C.confdMaxClockSkew)) $ \ good_delta ->
let encoded = J.encode crq
salt = show timestamp
signed = J.encode $ Confd.Utils.signMessage key salt encoded
good_timestamp = timestamp + if pm then good_delta else (good_delta)
bad_delta' = fromIntegral C.confdMaxClockSkew + bad_delta
bad_timestamp = timestamp + if pm then bad_delta' else (bad_delta')
ts_ok = Confd.Utils.parseRequest key signed good_timestamp
ts_bad = Confd.Utils.parseRequest key signed bad_timestamp
in counterexample "Failed to parse good message"
(ts_ok ==? BasicTypes.Ok (encoded, crq)) .&&.
counterexample ("Managed to deserialise message with bad\
\ timestamp, got " ++ show ts_bad)
(ts_bad ==? BasicTypes.Bad "Too old/too new timestamp or clock skew")
prop_rep_salt :: Hash.HashKey
-> Confd.ConfdReply
-> Property
prop_rep_salt hmac reply =
forAll arbitrary $ \salt1 ->
forAll (arbitrary `suchThat` (/= salt1)) $ \salt2 ->
let innerMsg = J.encode reply
msg = J.encode $ Confd.Utils.signMessage hmac salt1 innerMsg
in
Confd.Utils.parseReply hmac msg salt1 ==? BasicTypes.Ok (innerMsg, reply)
.&&. Confd.Utils.parseReply hmac msg salt2 ==?
BasicTypes.Bad "The received salt differs from the expected salt"
prop_bad_key :: String
-> Confd.ConfdRequest
-> Property
prop_bad_key salt crq =
forAll (vector 20) $ \key_sign ->
forAll (vector 20 `suchThat` (/= key_sign)) $ \key_verify ->
let signed = Confd.Utils.signMessage key_sign salt (J.encode crq)
encoded = J.encode signed
in counterexample ("Accepted message signed with different key" ++ encoded) $
(Confd.Utils.parseSignedMessage key_verify encoded
:: BasicTypes.Result (String, String, Confd.ConfdRequest)) ==?
BasicTypes.Bad "HMAC verification failed"
testSuite "Confd/Utils"
[ 'prop_req_sign
, 'prop_rep_salt
, 'prop_bad_key
]