summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2016-01-24 14:47:32 -0500
committerAndrew Cady <d@jerkface.net>2016-01-24 15:22:39 -0500
commit7f1b6358cd96d9ea204e36a5b721113635006cac (patch)
treec4009c521a388dc6f0867ffa4d571c7f0ae08512
parent08e001c5d4a620298f4d08d5d766082578e0233d (diff)
Don't save CSR to disk; cleanup
-rw-r--r--acme-certify.hs34
1 files changed, 16 insertions, 18 deletions
diff --git a/acme-certify.hs b/acme-certify.hs
index d127e03..5a50265 100644
--- a/acme-certify.hs
+++ b/acme-certify.hs
@@ -12,13 +12,10 @@
12module Main where 12module Main where
13 13
14import BasePrelude 14import BasePrelude
15import qualified Data.ByteString as B
16import qualified Data.ByteString.Lazy.Char8 as LC 15import qualified Data.ByteString.Lazy.Char8 as LC
17import Data.Coerce
18import Network.ACME (CSR (..), canProvision, certify, 16import Network.ACME (CSR (..), canProvision, certify,
19 ensureWritableDir, readKeyFile, 17 ensureWritableDir, (</>))
20 (</>)) 18import Network.ACME.Encoding (Keys (..), readKeys, toStrict)
21import Network.ACME.Encoding (Keys (..), toStrict)
22import Network.URI 19import Network.URI
23import OpenSSL 20import OpenSSL
24import OpenSSL.EVP.Digest 21import OpenSSL.EVP.Digest
@@ -92,11 +89,12 @@ cmdopts = CmdOpts <$> strOption (long "key" <> metavar "FILE" <>
92 , "(generated certificates will not be trusted!)" 89 , "(generated certificates will not be trusted!)"
93 ])) 90 ]))
94 91
95genKey :: String -> IO () 92genKey :: FilePath -> IO String
96genKey privKeyFile = withOpenSSL $ do 93genKey privKeyFile = withOpenSSL $ do
97 kp <- generateRSAKey' 4096 65537 94 kp <- generateRSAKey' 4096 65537
98 pem <- writePKCS8PrivateKey kp Nothing 95 pem <- writePKCS8PrivateKey kp Nothing
99 writeFile privKeyFile pem 96 writeFile privKeyFile pem
97 return pem
100 98
101genReq :: Keys -> [DomainName] -> IO CSR 99genReq :: Keys -> [DomainName] -> IO CSR
102genReq _ [] = error "genReq called with zero domains" 100genReq _ [] = error "genReq called with zero domains"
@@ -112,36 +110,33 @@ genReq (Keys priv pub) domains@(domain:_) = withOpenSSL $ do
112 where 110 where
113 nidSubjectAltName = 85 111 nidSubjectAltName = 85
114 112
115otherwiseM :: Monad m => m Bool -> m () -> m () 113getOrCreateKeys :: FilePath -> IO (Maybe Keys)
116a `otherwiseM` b = a >>= flip unless b 114getOrCreateKeys file = do
117infixl 0 `otherwiseM` 115 exists <- doesFileExist file
116 readKeys =<< if exists then readFile file else genKey file
118 117
119go :: CmdOpts -> IO () 118go :: CmdOpts -> IO ()
120go CmdOpts { .. } = do 119go CmdOpts { .. } = do
121 let terms = fromMaybe defaultTerms (join $ parseAbsoluteURI <$> optTerms) 120 let terms = fromMaybe defaultTerms (join $ parseAbsoluteURI <$> optTerms)
122 directoryUrl = if optStaging then stagingDirectoryUrl else liveDirectoryUrl 121 directoryUrl = if optStaging then stagingDirectoryUrl else liveDirectoryUrl
123 domainKeyFile = domainDir </> "rsa.key" 122 domainKeyFile = domainDir </> "rsa.key"
124 domainCSRFile = domainDir </> "csr.der"
125 domainCertFile = domainDir </> "cert.der" 123 domainCertFile = domainDir </> "cert.der"
126 domainDir = fromMaybe (head optDomains) optDomainDir 124 domainDir = fromMaybe (head optDomains) optDomainDir
127 privKeyFile = optKeyFile 125 privKeyFile = optKeyFile
128 requestDomains = fromMaybe (error "invalid domain name") $ sequence $ domainName . fromString <$> optDomains 126 requestDomains = fromMaybe (error "invalid domain name") $ sequence $ domainName . fromString <$> optDomains
129 127
130 doesFileExist privKeyFile `otherwiseM` genKey privKeyFile
131
132 doesDirectoryExist domainDir `otherwiseM` createDirectory domainDir 128 doesDirectoryExist domainDir `otherwiseM` createDirectory domainDir
133 doesFileExist domainKeyFile `otherwiseM` genKey domainKeyFile
134 129
135 Just keys <- readKeyFile privKeyFile 130 Just domainKeys <- getOrCreateKeys domainKeyFile
131 Just keys <- getOrCreateKeys privKeyFile
136 132
137 challengeDir <- ensureWritableDir optChallengeDir "challenge directory" 133 challengeDir <- ensureWritableDir optChallengeDir "challenge directory"
138 void $ ensureWritableDir domainDir "domain directory" 134 void $ ensureWritableDir domainDir "domain directory"
139 135
140 forM_ requestDomains $ canProvision challengeDir >=> (`unless` error "Error: cannot provision files to web server via challenge directory") 136 forM_ requestDomains $ canProvision challengeDir >=>
137 (`unless` error "Error: cannot provision files to web server via challenge directory")
141 138
142 csrData <- fromMaybe (error "Error: failed to read domain key file") <$> 139 csrData <- genReq domainKeys requestDomains
143 readKeyFile domainKeyFile >>= flip genReq requestDomains
144 B.writeFile domainCSRFile (coerce csrData)
145 140
146 let email = either (error . ("Error: invalid email address: " ++)) id . validate . fromString <$> optEmail 141 let email = either (error . ("Error: invalid email address: " ++)) id . validate . fromString <$> optEmail
147 142
@@ -149,3 +144,6 @@ go CmdOpts { .. } = do
149 144
150 either (error . ("Error: " ++)) (LC.writeFile domainCertFile) certificate 145 either (error . ("Error: " ++)) (LC.writeFile domainCertFile) certificate
151 146
147otherwiseM :: Monad m => m Bool -> m () -> m ()
148a `otherwiseM` b = a >>= flip unless b
149infixl 0 `otherwiseM`