module Propellor.Property.LetsEncrypt where
import Propellor.Base
import qualified Propellor.Property.Apt as Apt
import System.Posix.Files
installed :: Property DebianLike
installed :: Property DebianLike
installed = [Package] -> Property DebianLike
Apt.installed [Package
"certbot"]
data AgreeTOS = AgreeTOS (Maybe Email)
type Email = String
type WebRoot = FilePath
letsEncrypt :: AgreeTOS -> Domain -> WebRoot -> Property DebianLike
letsEncrypt :: AgreeTOS -> Package -> Package -> Property DebianLike
letsEncrypt AgreeTOS
tos Package
domain = AgreeTOS -> Package -> [Package] -> Package -> Property DebianLike
letsEncrypt' AgreeTOS
tos Package
domain []
letsEncrypt' :: AgreeTOS -> Domain -> [Domain] -> WebRoot -> Property DebianLike
letsEncrypt' :: AgreeTOS -> Package -> [Package] -> Package -> Property DebianLike
letsEncrypt' (AgreeTOS Maybe Package
memail) Package
domain [Package]
domains Package
webroot =
Property UnixLike
prop forall x y. Combines x y => x -> y -> CombinedType x y
`requires` Property DebianLike
installed
where
prop :: Property UnixLike
prop :: Property UnixLike
prop = forall {k} (metatypes :: k).
SingI metatypes =>
Package -> Propellor Result -> Property (MetaTypes metatypes)
property Package
desc forall a b. (a -> b) -> a -> b
$ do
[[Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime)]]
startstats <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO [[Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime)]]
getstats
(Package
transcript, Bool
ok) <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$
Package -> [Package] -> Maybe Package -> IO (Package, Bool)
processTranscript Package
"letsencrypt" [Package]
params forall a. Maybe a
Nothing
if Bool
ok
then do
[[Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime)]]
endstats <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO [[Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime)]]
getstats
if [[Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime)]]
startstats forall a. Eq a => a -> a -> Bool
/= [[Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime)]]
endstats
then forall (m :: * -> *) a. Monad m => a -> m a
return Result
MadeChange
else forall (m :: * -> *) a. Monad m => a -> m a
return Result
NoChange
else do
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ Handle -> Package -> IO ()
hPutStr Handle
stderr Package
transcript
forall (m :: * -> *) a. Monad m => a -> m a
return Result
FailedChange
desc :: Package
desc = Package
"letsencrypt " forall a. [a] -> [a] -> [a]
++ [Package] -> Package
unwords [Package]
alldomains
alldomains :: [Package]
alldomains = Package
domain forall a. a -> [a] -> [a]
: [Package]
domains
params :: [Package]
params =
[ Package
"certonly"
, Package
"--agree-tos"
, case Maybe Package
memail of
Just Package
email -> Package
"--email="forall a. [a] -> [a] -> [a]
++Package
email
Maybe Package
Nothing -> Package
"--register-unsafely-without-email"
, Package
"--webroot"
, Package
"--webroot-path", Package
webroot
, Package
"--text"
, Package
"--noninteractive"
, Package
"--keep-until-expiring"
, Package
"--expand"
] forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map (\Package
d -> Package
"--domain="forall a. [a] -> [a] -> [a]
++Package
d) [Package]
alldomains
getstats :: IO [[Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime)]]
getstats = forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Package
-> IO [Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime)]
statcertfiles [Package]
alldomains
statcertfiles :: Package
-> IO [Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime)]
statcertfiles Package
d = forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Package
-> IO (Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime))
statfile
[ Package -> Package
certFile Package
d
, Package -> Package
privKeyFile Package
d
, Package -> Package
chainFile Package
d
, Package -> Package
fullChainFile Package
d
]
statfile :: Package
-> IO (Maybe (FileID, DeviceID, FileMode, FileOffset, EpochTime))
statfile Package
f = forall (m :: * -> *) a. MonadCatch m => m a -> m (Maybe a)
catchMaybeIO forall a b. (a -> b) -> a -> b
$ do
FileStatus
s <- Package -> IO FileStatus
getFileStatus Package
f
forall (m :: * -> *) a. Monad m => a -> m a
return (FileStatus -> FileID
fileID FileStatus
s, FileStatus -> DeviceID
deviceID FileStatus
s, FileStatus -> FileMode
fileMode FileStatus
s, FileStatus -> FileOffset
fileSize FileStatus
s, FileStatus -> EpochTime
modificationTime FileStatus
s)
liveCertDir :: Domain -> FilePath
liveCertDir :: Package -> Package
liveCertDir Package
d = Package
"/etc/letsencrypt/live" Package -> Package -> Package
</> Package
d
certFile :: Domain -> FilePath
certFile :: Package -> Package
certFile Package
d = Package -> Package
liveCertDir Package
d Package -> Package -> Package
</> Package
"cert.pem"
privKeyFile :: Domain -> FilePath
privKeyFile :: Package -> Package
privKeyFile Package
d = Package -> Package
liveCertDir Package
d Package -> Package -> Package
</> Package
"privkey.pem"
chainFile :: Domain -> FilePath
chainFile :: Package -> Package
chainFile Package
d = Package -> Package
liveCertDir Package
d Package -> Package -> Package
</> Package
"chain.pem"
fullChainFile :: Domain -> FilePath
fullChainFile :: Package -> Package
fullChainFile Package
d = Package -> Package
liveCertDir Package
d Package -> Package -> Package
</> Package
"fullchain.pem"