Statistics
| Branch: | Tag: | Revision:

root / htools / Ganeti / Confd / Utils.hs @ 5bfcd75f

History | View | Annotate | Download (2.8 kB)

1 62377cf5 Iustin Pop
{-| Implementation of the Ganeti confd utilities.
2 62377cf5 Iustin Pop
3 62377cf5 Iustin Pop
This holds a few utility functions that could be useful in both
4 62377cf5 Iustin Pop
clients and servers.
5 62377cf5 Iustin Pop
6 62377cf5 Iustin Pop
-}
7 62377cf5 Iustin Pop
8 62377cf5 Iustin Pop
{-
9 62377cf5 Iustin Pop
10 62377cf5 Iustin Pop
Copyright (C) 2011, 2012 Google Inc.
11 62377cf5 Iustin Pop
12 62377cf5 Iustin Pop
This program is free software; you can redistribute it and/or modify
13 62377cf5 Iustin Pop
it under the terms of the GNU General Public License as published by
14 62377cf5 Iustin Pop
the Free Software Foundation; either version 2 of the License, or
15 62377cf5 Iustin Pop
(at your option) any later version.
16 62377cf5 Iustin Pop
17 62377cf5 Iustin Pop
This program is distributed in the hope that it will be useful, but
18 62377cf5 Iustin Pop
WITHOUT ANY WARRANTY; without even the implied warranty of
19 62377cf5 Iustin Pop
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20 62377cf5 Iustin Pop
General Public License for more details.
21 62377cf5 Iustin Pop
22 62377cf5 Iustin Pop
You should have received a copy of the GNU General Public License
23 62377cf5 Iustin Pop
along with this program; if not, write to the Free Software
24 62377cf5 Iustin Pop
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 62377cf5 Iustin Pop
02110-1301, USA.
26 62377cf5 Iustin Pop
27 62377cf5 Iustin Pop
-}
28 62377cf5 Iustin Pop
29 62377cf5 Iustin Pop
module Ganeti.Confd.Utils
30 62377cf5 Iustin Pop
  ( getClusterHmac
31 5bfcd75f Michele Tartara
  , parseSignedMessage
32 62377cf5 Iustin Pop
  , parseMessage
33 62377cf5 Iustin Pop
  , signMessage
34 46300ac2 Michele Tartara
  , getCurrentTime
35 62377cf5 Iustin Pop
  ) where
36 62377cf5 Iustin Pop
37 62377cf5 Iustin Pop
import qualified Data.ByteString as B
38 62377cf5 Iustin Pop
import qualified Text.JSON as J
39 46300ac2 Michele Tartara
import System.Time
40 62377cf5 Iustin Pop
41 62377cf5 Iustin Pop
import Ganeti.BasicTypes
42 cdc2392b Iustin Pop
import Ganeti.Confd.Types
43 62377cf5 Iustin Pop
import Ganeti.Hash
44 62377cf5 Iustin Pop
import qualified Ganeti.Constants as C
45 9eeb0aa5 Michael Hanselmann
import qualified Ganeti.Path as Path
46 f3baf5ef Iustin Pop
import Ganeti.JSON
47 26d62e4c Iustin Pop
import Ganeti.Utils
48 62377cf5 Iustin Pop
49 9d3867b1 Iustin Pop
-- | Type-adjusted max clock skew constant.
50 9d3867b1 Iustin Pop
maxClockSkew :: Integer
51 9d3867b1 Iustin Pop
maxClockSkew = fromIntegral C.confdMaxClockSkew
52 9d3867b1 Iustin Pop
53 62377cf5 Iustin Pop
-- | Returns the HMAC key.
54 62377cf5 Iustin Pop
getClusterHmac :: IO HashKey
55 29a30533 Iustin Pop
getClusterHmac = Path.confdHmacKey >>= fmap B.unpack . B.readFile
56 62377cf5 Iustin Pop
57 5bfcd75f Michele Tartara
-- | Parses a signed message.
58 5bfcd75f Michele Tartara
parseSignedMessage :: (J.JSON a) => HashKey -> String
59 5bfcd75f Michele Tartara
                   -> Result (String, String, a)
60 5bfcd75f Michele Tartara
parseSignedMessage key str = do
61 5bfcd75f Michele Tartara
  (SignedMessage hmac msg salt) <- fromJResult "parsing signed message"
62 5bfcd75f Michele Tartara
    $ J.decode str
63 5bfcd75f Michele Tartara
  parsedMsg <- if verifyMac key (Just salt) msg hmac
64 62377cf5 Iustin Pop
           then fromJResult "parsing message" $ J.decode msg
65 62377cf5 Iustin Pop
           else Bad "HMAC verification failed"
66 5bfcd75f Michele Tartara
  return (salt, msg, parsedMsg)
67 62377cf5 Iustin Pop
68 63e166a5 Michele Tartara
-- | Message parsing. This can either result in a good, valid message,
69 62377cf5 Iustin Pop
-- or fail in the Result monad.
70 62377cf5 Iustin Pop
parseMessage :: HashKey -> String -> Integer
71 62377cf5 Iustin Pop
             -> Result (String, ConfdRequest)
72 62377cf5 Iustin Pop
parseMessage hmac msg curtime = do
73 5bfcd75f Michele Tartara
  (salt, origmsg, request) <- parseSignedMessage hmac msg
74 62377cf5 Iustin Pop
  ts <- tryRead "Parsing timestamp" salt::Result Integer
75 9d3867b1 Iustin Pop
  if abs (ts - curtime) > maxClockSkew
76 62377cf5 Iustin Pop
    then fail "Too old/too new timestamp or clock skew"
77 62377cf5 Iustin Pop
    else return (origmsg, request)
78 62377cf5 Iustin Pop
79 62377cf5 Iustin Pop
-- | Signs a message with a given key and salt.
80 62377cf5 Iustin Pop
signMessage :: HashKey -> String -> String -> SignedMessage
81 62377cf5 Iustin Pop
signMessage key salt msg =
82 62377cf5 Iustin Pop
  SignedMessage { signedMsgMsg  = msg
83 62377cf5 Iustin Pop
                , signedMsgSalt = salt
84 62377cf5 Iustin Pop
                , signedMsgHmac = hmac
85 62377cf5 Iustin Pop
                }
86 62377cf5 Iustin Pop
    where hmac = computeMac key (Just salt) msg
87 46300ac2 Michele Tartara
88 46300ac2 Michele Tartara
-- | Returns the current time.
89 46300ac2 Michele Tartara
getCurrentTime :: IO Integer
90 46300ac2 Michele Tartara
getCurrentTime = do
91 46300ac2 Michele Tartara
  TOD ctime _ <- getClockTime
92 46300ac2 Michele Tartara
  return ctime