summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2016-04-09 22:01:33 -0400
committerAndrew Cady <d@jerkface.net>2016-04-09 22:01:33 -0400
commite26676c87b074b3933dd1d5c73cd62dcf2ca1995 (patch)
treef17d621018b72b0d9cc7001000687f8eaaffda4d
parent70137d8dba49353f525b4d3e93a919df80e81765 (diff)
Specify remote provisioning paths in config file
-rw-r--r--acme-certify.hs58
1 files changed, 40 insertions, 18 deletions
diff --git a/acme-certify.hs b/acme-certify.hs
index 5f4613f..3afcfc3 100644
--- a/acme-certify.hs
+++ b/acme-certify.hs
@@ -176,26 +176,29 @@ runUpdate UpdateOpts { .. } = do
176 176
177 Just keys <- getOrCreateKeys $ globalCertificateDir </> "rsa.key" 177 Just keys <- getOrCreateKeys $ globalCertificateDir </> "rsa.key"
178 178
179 179 let certSpecs = flip map certReqDomains $ \(host, domains) -> case dereference $ map (chooseProvisioner host) domains of
180 certSpecs :: [CertSpec] <- forM certReqDomains $ \(host, domains) -> do 180 Just provisioners -> certSpec globalCertificateDir keys (host, provisioners)
181 provisioners <- mapM (chooseProvisioner host) domains 181 Nothing -> error "invalid configuration file"
182 return $ certSpec globalCertificateDir keys (host, provisioners)
183 182
184 mapM_ print certSpecs 183 mapM_ print certSpecs
185 184
186 h <- remoteTemp "localhost" "/tmp/whatevs 'bro'" "this content\ncontains stuff'" 185 h <- remoteTemp "localhost" "/tmp/whatevs 'bro'" "this content\ncontains stuff'"
187 threadDelay $ 1000*1000*10 186 threadDelay $ 1000 * 1000 * 10
188 removeTemp h 187 removeTemp h
189 188
190 error "Error: unimplemented" 189 error "Error: unimplemented"
191 190
192 where 191 where
193 chooseProvisioner :: String -> String -> IO (DomainName, HttpProvisioner) 192 dereference :: [(DomainName, Either DomainName HttpProvisioner)] -> Maybe [(DomainName, HttpProvisioner)]
194 chooseProvisioner host domain -- TODO: implement 193 dereference xs = plumb $ xs <&> fmap (either deref Just)
195 = do 194 where
196 let errmsg = "whatever" 195 deref :: DomainName -> Maybe HttpProvisioner
197 dir <- ensureWritableDir "/var/www/html/.well-known/acme-challenge/" errmsg 196 deref s = lookup s xs & preview (_Just . _Right)
198 return (domainName' domain, provisionViaFile dir) 197 plumb = traverse (\(a, b) -> fmap ((,) a) b)
198
199 chooseProvisioner :: String -> VHostSpec -> (DomainName, Either DomainName HttpProvisioner)
200 chooseProvisioner host (VHostSpec domain pathInfo) =
201 (domain, provisionViaRemoteFile host <$> pathInfo)
199 202
200 certSpec :: FilePath -> Keys -> (String, [(DomainName, HttpProvisioner)]) -> CertSpec 203 certSpec :: FilePath -> Keys -> (String, [(DomainName, HttpProvisioner)]) -> CertSpec
201 certSpec baseDir keys (host, requestDomains) = CertSpec { .. } 204 certSpec baseDir keys (host, requestDomains) = CertSpec { .. }
@@ -205,10 +208,28 @@ runUpdate UpdateOpts { .. } = do
205 csUserKeys = keys 208 csUserKeys = keys
206 csCertificateDir = baseDir </> host </> (show . fst) (head requestDomains) 209 csCertificateDir = baseDir </> host </> (show . fst) (head requestDomains)
207 210
208 combineSubdomains :: AsPrimitive v => Text -> HashMap.HashMap Text v -> [String] 211 combineSubdomains :: AsPrimitive v => Text -> HashMap.HashMap Text v -> [VHostSpec]
209 combineSubdomains domain subs = 212 combineSubdomains domain subs =
210 map (<..> unpack domain) $ sort -- relying on the fact that '.' sorts first 213 map (makeVHostSpec (domainName' $ unpack domain)) $
211 $ concat $ HashMap.lookup domain subs & toListOf (_Just . _String . to (words . unpack)) 214 sort -- relying on the fact that '.' sorts first
215 $ concat $ HashMap.lookup domain subs & toListOf (_Just . _String . to (words . unpack))
216
217data VHostSpec = VHostSpec DomainName (Either DomainName FilePath) deriving Show
218makeVHostSpec :: DomainName -> String -> VHostSpec
219makeVHostSpec = make
220 where
221 make (show -> parentDomain) (splitSpec -> (sub, spec)) =
222 VHostSpec (domainName' $ sub <..> parentDomain) (makeRef spec)
223 where
224 makeRef :: Either String FilePath -> Either DomainName FilePath
225 makeRef = left (\refSub -> domainName' $ refSub <..> parentDomain)
226
227 splitSpec :: String -> (String, Either String FilePath)
228 splitSpec (break (== '{') -> (a, b)) = (,) a $
229 case b of
230 ('{':c@('/':_)) -> Right $ takeWhile (/= '}') c
231 ('{':c) -> Left $ takeWhile (/= '}') c
232 _ -> Right $ "/srv" </> a </> "public_html"
212 233
213data TempRemover = TempRemover { removeTemp :: IO () } 234data TempRemover = TempRemover { removeTemp :: IO () }
214remoteTemp :: String -> FilePath -> String -> IO TempRemover 235remoteTemp :: String -> FilePath -> String -> IO TempRemover
@@ -226,7 +247,8 @@ provisionViaRemoteFile :: String -> FilePath -> HttpProvisioner
226provisionViaRemoteFile = provision 247provisionViaRemoteFile = provision
227 where 248 where
228 provision host dir (bsToS -> tok) (bsToS -> thumbtoken) = 249 provision host dir (bsToS -> tok) (bsToS -> thumbtoken) =
229 void $ allocate (liftIO $ remoteTemp host (dir </> tok) thumbtoken) removeTemp 250 void $ allocate (liftIO $ remoteTemp host (dir </> wk </> tok) thumbtoken) removeTemp
251 wk = ".well-known/acme-challenge"
230 bsToS = unpack . decodeUtf8 252 bsToS = unpack . decodeUtf8
231 253
232runCertify :: CertifyOpts -> IO (Either String ()) 254runCertify :: CertifyOpts -> IO (Either String ())
@@ -257,10 +279,10 @@ runCertify CertifyOpts{..} = do
257 forM_ csDomains $ uncurry canProvision >=> 279 forM_ csDomains $ uncurry canProvision >=>
258 (`unless` error "Error: cannot provision files to web server") 280 (`unless` error "Error: cannot provision files to web server")
259 281
260 go' directoryUrl terms email issuerCert req 282 fetchCertificate directoryUrl terms email issuerCert req
261 283
262go' :: URI -> URI -> Maybe EmailAddress -> X509 -> CertSpec -> IO (Either String ()) 284fetchCertificate :: URI -> URI -> Maybe EmailAddress -> X509 -> CertSpec -> IO (Either String ())
263go' directoryUrl terms email issuerCert cs@CertSpec{..} = do 285fetchCertificate directoryUrl terms email issuerCert cs@CertSpec{..} = do
264 Just domainKeys <- getOrCreateKeys $ csCertificateDir </> "rsa.key" 286 Just domainKeys <- getOrCreateKeys $ csCertificateDir </> "rsa.key"
265 dh <- saveDhParams cs 287 dh <- saveDhParams cs
266 288