summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2016-04-09 23:07:34 -0400
committerAndrew Cady <d@jerkface.net>2016-04-09 23:08:23 -0400
commit2aceca9e7c7e0d39efc66a65168ceb3d9c587be5 (patch)
tree0eae378dba49919cab38d2ecddf948379d99ff27
parent2767871a0dc502b369a9baa0a6f55dc541cc1e13 (diff)
successfully retrieved certificate with update code
-rw-r--r--acme-certify.hs34
1 files changed, 25 insertions, 9 deletions
diff --git a/acme-certify.hs b/acme-certify.hs
index 5f4c24d..15b729f 100644
--- a/acme-certify.hs
+++ b/acme-certify.hs
@@ -21,8 +21,8 @@ import Control.Monad.IO.Class
21import Control.Monad.Trans.Resource 21import Control.Monad.Trans.Resource
22import Data.Aeson.Lens 22import Data.Aeson.Lens
23import qualified Data.HashMap.Strict as HashMap 23import qualified Data.HashMap.Strict as HashMap
24import Data.Text (Text, unpack) 24import Data.Text (Text, unpack, pack)
25import Data.Text.Encoding (decodeUtf8) 25import Data.Text.Encoding (decodeUtf8, encodeUtf8)
26import Data.Yaml (Object) 26import Data.Yaml (Object)
27import qualified Data.Yaml.Config as Config 27import qualified Data.Yaml.Config as Config
28import Data.Yaml.Config.Internal (Config (..)) 28import Data.Yaml.Config.Internal (Config (..))
@@ -187,13 +187,23 @@ runUpdate UpdateOpts { .. } = do
187 threadDelay $ 1000 * 1000 * 10 187 threadDelay $ 1000 * 1000 * 10
188 removeTemp h 188 removeTemp h
189 189
190 issuerCert <- readX509 letsEncryptX1CrossSigned
191
190 forM_ certReqDomains $ \(host, domains) -> do 192 forM_ certReqDomains $ \(host, domains) -> do
191 when (host == "fifty") $ do 193 when (host == "fifty") $ do
192 putStrLn host 194 putStrLn host
193 let cs = dereference (map (chooseProvisioner host) domains) <&> certSpec globalCertificateDir keys host 195 let Just spec = dereference (map (chooseProvisioner host) domains) <&> certSpec globalCertificateDir keys host
194 print cs 196 print spec
195 error "Error: unimplemented" 197
196 198 when True $
199 forM_ (csDomains spec) $ uncurry canProvision >=>
200 (`unless` error "Error: cannot provision files to web server")
201 let terms = defaultTerms
202 directoryUrl = stagingDirectoryUrl
203 email = emailAddress $ encodeUtf8 . pack $ "root@" ++ (domainToString . fst . head) (csDomains spec)
204 print =<< fetchCertificate directoryUrl terms email issuerCert spec
205
206 error "Error: unimplemented"
197 where 207 where
198 208
199 dereference :: [(DomainName, Either DomainName HttpProvisioner)] -> Maybe [(DomainName, HttpProvisioner)] 209 dereference :: [(DomainName, Either DomainName HttpProvisioner)] -> Maybe [(DomainName, HttpProvisioner)]
@@ -245,14 +255,19 @@ data TempRemover = TempRemover { removeTemp :: IO () }
245remoteTemp :: String -> FilePath -> String -> IO TempRemover 255remoteTemp :: String -> FilePath -> String -> IO TempRemover
246remoteTemp host fileName content = do 256remoteTemp host fileName content = do
247 (inp,out,err,_pid) <- ssh $ unlines 257 (inp,out,err,_pid) <- ssh $ unlines
248 [ "printf '%s' " ++ escape content ++ " > " ++ escape fileName 258 [ "mkdir -p " ++ escape (dirname fileName)
259 , "printf '%s' " ++ escape content ++ " > " ++ escape fileName
260 , "echo provisioned."
249 , "trap " ++ (escape . unwords) ["rm -f", escape fileName] ++ " EXIT" 261 , "trap " ++ (escape . unwords) ["rm -f", escape fileName] ++ " EXIT"
250 , "read line" 262 , "read line"
251 ] 263 ]
264 void $ hGetLine out
252 return $ TempRemover $ mapM_ hClose [inp, out, err] 265 return $ TempRemover $ mapM_ hClose [inp, out, err]
253 where 266 where
254 ssh cmd = runInteractiveProcess "ssh" (host : words "-- sh -c" ++ [escape cmd]) Nothing Nothing 267 ssh cmd = runInteractiveProcess "ssh" (host : words "-- sh -c" ++ [escape cmd]) Nothing Nothing
255 268
269dirname = dropWhileEnd (/= '/')
270
256provisionViaRemoteFile :: String -> FilePath -> HttpProvisioner 271provisionViaRemoteFile :: String -> FilePath -> HttpProvisioner
257provisionViaRemoteFile = provision 272provisionViaRemoteFile = provision
258 where 273 where
@@ -279,7 +294,7 @@ runCertify CertifyOpts{..} = do
279 294
280 Just keys <- getOrCreateKeys privKeyFile 295 Just keys <- getOrCreateKeys privKeyFile
281 296
282 let req = CertSpec {..} 297 let spec = CertSpec {..}
283 csDomains = map (flip (,) (provisionViaFile challengeDir)) requestDomains 298 csDomains = map (flip (,) (provisionViaFile challengeDir)) requestDomains
284 csSkipDH = optSkipDH 299 csSkipDH = optSkipDH
285 csUserKeys = keys 300 csUserKeys = keys
@@ -289,7 +304,7 @@ runCertify CertifyOpts{..} = do
289 forM_ csDomains $ uncurry canProvision >=> 304 forM_ csDomains $ uncurry canProvision >=>
290 (`unless` error "Error: cannot provision files to web server") 305 (`unless` error "Error: cannot provision files to web server")
291 306
292 fetchCertificate directoryUrl terms email issuerCert req 307 fetchCertificate directoryUrl terms email issuerCert spec
293 308
294fetchCertificate :: URI -> URI -> Maybe EmailAddress -> X509 -> CertSpec -> IO (Either String ()) 309fetchCertificate :: URI -> URI -> Maybe EmailAddress -> X509 -> CertSpec -> IO (Either String ())
295fetchCertificate directoryUrl terms email issuerCert cs@CertSpec{..} = do 310fetchCertificate directoryUrl terms email issuerCert cs@CertSpec{..} = do
@@ -321,6 +336,7 @@ genKey = withOpenSSL $ do
321getOrCreate :: IO String -> (String -> IO a) -> FilePath -> IO a 336getOrCreate :: IO String -> (String -> IO a) -> FilePath -> IO a
322getOrCreate gen parse file = do 337getOrCreate gen parse file = do
323 exists <- doesFileExist file 338 exists <- doesFileExist file
339 createDirectoryIfMissing True (dirname file)
324 parse =<< if exists then readFile file else gen >>= save file 340 parse =<< if exists then readFile file else gen >>= save file
325 where 341 where
326 save f x = writeFile f x >> return x 342 save f x = writeFile f x >> return x