summaryrefslogtreecommitdiff
path: root/src/Network/ACME.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Network/ACME.hs')
-rw-r--r--src/Network/ACME.hs21
1 files changed, 10 insertions, 11 deletions
diff --git a/src/Network/ACME.hs b/src/Network/ACME.hs
index 2c58bac..2312389 100644
--- a/src/Network/ACME.hs
+++ b/src/Network/ACME.hs
@@ -2,6 +2,7 @@
2{-# LANGUAGE MultiParamTypeClasses #-} 2{-# LANGUAGE MultiParamTypeClasses #-}
3{-# LANGUAGE OverloadedStrings #-} 3{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE ScopedTypeVariables #-} 4{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE ViewPatterns #-}
5 6
6-------------------------------------------------------------------------------- 7--------------------------------------------------------------------------------
7-- | Get a certificate from Let's Encrypt using the ACME protocol. 8-- | Get a certificate from Let's Encrypt using the ACME protocol.
@@ -57,7 +58,7 @@ certify directoryUrl keys reg provision certReq =
57 forM_ reg $ uncurry register >=> statusReport 58 forM_ reg $ uncurry register >=> statusReport
58 59
59 let performChallenge domain (ChallengeRequest nextUri token thumbtoken) = do 60 let performChallenge domain (ChallengeRequest nextUri token thumbtoken) = do
60 liftResourceT $ provision (acmeChallengeURI domain token) thumbtoken 61 liftResourceT $ provision domain token thumbtoken
61 notifyChallenge nextUri thumbtoken >>= statusReport >>= ncErrorReport 62 notifyChallenge nextUri thumbtoken >>= statusReport >>= ncErrorReport
62 63
63 cr dom = challengeRequest dom >>= statusReport >>= extractCR >>= performChallenge dom 64 cr dom = challengeRequest dom >>= statusReport >>= extractCR >>= performChallenge dom
@@ -83,15 +84,15 @@ pollResults (link:links) = do
83 84
84-- Provisioner callback 85-- Provisioner callback
85 86
86type HttpProvisioner = URI -> ByteString -> ResIO () 87type HttpProvisioner = DomainName -> ByteString -> ByteString -> ResIO ()
87fileProvisioner :: WritableDir -> HttpProvisioner 88fileProvisioner :: (DomainName -> Maybe WritableDir) -> HttpProvisioner
88fileProvisioner challengeDir uri thumbtoken = do 89fileProvisioner challengeDir (challengeDir -> Just dir) tok thumbtoken = do
89 void $ allocate (return f) removeFile 90 void $ allocate (return f) removeFile
90 liftIO $ BC.writeFile f thumbtoken 91 liftIO $ BC.writeFile f thumbtoken
91 92
92 where 93 where
93 f = (coerce challengeDir </>) . takeWhileEnd (/= '/') . uriPath $ uri 94 f = (coerce dir </>) (T.unpack $ decodeUtf8 tok)
94 takeWhileEnd s = reverse . takeWhile s . reverse 95fileProvisioner _ dom _ _ = liftIO $ fail $ "fileProvisioner: no writable directory for domain: " ++ show dom
95 96
96newtype WritableDir = WritableDir String 97newtype WritableDir = WritableDir String
97ensureWritableDir :: FilePath -> String -> IO WritableDir 98ensureWritableDir :: FilePath -> String -> IO WritableDir
@@ -100,15 +101,13 @@ ensureWritableDir file name = do
100 return $ WritableDir file 101 return $ WritableDir file
101 where e n = error $ "Error: " ++ n ++ " is not writable" 102 where e n = error $ "Error: " ++ n ++ " is not writable"
102 103
103canProvision :: WritableDir -> DomainName -> IO Bool 104canProvision :: (DomainName -> Maybe WritableDir) -> DomainName -> IO Bool
104canProvision challengeDir domain = do 105canProvision challengeDir domain = do
105 token <- (".test." ++) . show <$> getPOSIXTime 106 token <- (".test." ++) . show <$> getPOSIXTime
106 107
107 let uri = acmeChallengeURI domain (fromString token)
108
109 r <- runResourceT $ do 108 r <- runResourceT $ do
110 fileProvisioner challengeDir uri (fromString token) 109 fileProvisioner challengeDir domain (fromString token) (fromString token)
111 liftIO $ W.get (show uri) 110 liftIO $ W.get $ show $ acmeChallengeURI domain (fromString token)
112 return $ r ^. responseBody == fromString token 111 return $ r ^. responseBody == fromString token
113 112
114-- The ACME monad 113-- The ACME monad