@@ -19,12 +19,18 @@ import Prelude hiding (id, (.))
1919import Control.Category (id, (.))
2020import Control.Arrow (arr)
2121import Control.Monad (forM)
22+import Control.Applicative ((<$>), (<*>))
2223import Data.Maybe (listToMaybe)
24+import Data.ByteString.Lazy (ByteString)
2325import Data.ByteString.Char8 as BSC (pack)
2426import Data.ByteString.Lazy.Char8 as BSLC (unpack)
25−import Network.TLS (PrivateKey)
27+import Data.Binary (Binary(get,put))
28+import Data.Binary.Put (runPut)
29+import Data.Binary.Get (Get, runGet)
30+import Network.TLS (PrivateKey(PrivRSA))
2631import Network.TLS.Extra (fileReadCertificate, fileReadPrivateKey)
27−import Data.Certificate.X509 (X509)
32+import Data.Certificate.X509 (X509, encodeCertificate, decodeCertificate)
33+import qualified Crypto.Types.PubKey.RSA as RSA (PrivateKey(..))
2834import Control.Monad.Trans.Resource (ResourceT)
2935import Control.Monad.IO.Class (liftIO)
3036import Control.Arrow.ArrowList (listA, arr2A)
@@ -161,6 +167,41 @@ data AzureSetup = AzureSetup
161167 , baseUrl :: String
162168 }
163169
170+-- TODO: it's dubious to be transferring private keys, but we transfer them
171+-- over a secure connection and it can be argued that it's safer than actually
172+-- storing the private key on each remote server
173+
174+encodePrivateKey :: PrivateKey -> ByteString
175+encodePrivateKey (PrivRSA pkey) = runPut $ do
176+ put (RSA.private_size pkey)
177+ put (RSA.private_n pkey)
178+ put (RSA.private_d pkey)
179+ put (RSA.private_p pkey)
180+ put (RSA.private_q pkey)
181+ put (RSA.private_dP pkey)
182+ put (RSA.private_dQ pkey)
183+ put (RSA.private_qinv pkey)
184+
185+decodePrivateKey :: ByteString -> PrivateKey
186+decodePrivateKey = PrivRSA . runGet getPrivateKey
187+ where
188+ getPrivateKey :: Get RSA.PrivateKey
189+ getPrivateKey =
190+ RSA.PrivateKey <$> get <*> get <*> get <*> get <*> get <*> get <*> get <*> get
191+
192+instance Binary AzureSetup where
193+ put (AzureSetup sid cert pkey url) = do
194+ put sid
195+ put (encodeCertificate cert)
196+ put (encodePrivateKey pkey)
197+ put url
198+ get = do
199+ sid <- get
200+ Right cert <- decodeCertificate <$> get
201+ pkey <- decodePrivateKey <$> get
202+ url <- get
203+ return $ AzureSetup sid cert pkey url
204+
164205-- | Initialize Azure
165206azureSetup :: String -- ^ Subscription ID
166207 -> String -- ^ Path to certificate