summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2016-04-09 03:23:34 -0400
committerAndrew Cady <d@jerkface.net>2016-04-09 03:25:30 -0400
commit5167199204f4d502e5c3b1a54d1fb5d88a043af1 (patch)
treeea948d5acb31a203d74947152ca400e26e47cfd7
parentddf8b7b2a5759fe80a667f5bb8f2a9bc9306a6f7 (diff)
Separate CLI into subcommands
Viz. 'update' and 'certify' 'certify' is just the previous CLI. 'update' is unimplemented. The binary was renamed from 'acme-certify' to 'acme' to reflect this.
-rw-r--r--acme-certify.cabal2
-rw-r--r--acme-certify.hs126
2 files changed, 79 insertions, 49 deletions
diff --git a/acme-certify.cabal b/acme-certify.cabal
index 42c4192..6424567 100644
--- a/acme-certify.cabal
+++ b/acme-certify.cabal
@@ -21,7 +21,7 @@ library
21 resourcet, file-embed 21 resourcet, file-embed
22 default-language: Haskell2010 22 default-language: Haskell2010
23 23
24executable acme-certify 24executable acme
25 -- hs-source-dirs: app 25 -- hs-source-dirs: app
26 main-is: acme-certify.hs 26 main-is: acme-certify.hs
27 ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall 27 ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall
diff --git a/acme-certify.hs b/acme-certify.hs
index 9d8d770..ae7b4cf 100644
--- a/acme-certify.hs
+++ b/acme-certify.hs
@@ -37,15 +37,30 @@ Just stagingDirectoryUrl = parseAbsoluteURI "https://acme-staging.api.letsencryp
37Just defaultTerms = parseAbsoluteURI "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf" 37Just defaultTerms = parseAbsoluteURI "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf"
38 38
39main :: IO () 39main :: IO ()
40main = execParser opts >>= go >>= either (error . ("Error: " ++)) return 40main = execParser (info opts idm) >>= run
41 where 41 where
42 opts = info (helper <*> cmdopts) (fullDesc <> progDesc detailedDescription <> Opt.header "Let's Encrypt! ACME client") 42 opts :: Parser Options
43 opts = Options <$> parseCommand
44 parseCommand :: Parser Command
45 parseCommand = subparser $
46 command "certify" (info (helper <*> certifyOpts) desc) <>
47 command "update" (info (helper <*> updateOpts) desc)
48 desc = fullDesc <> progDesc detailedDescription <> Opt.header "Let's Encrypt! ACME client"
43 detailedDescription = unwords 49 detailedDescription = unwords
44 [ "This program will generate a signed TLS certificate" 50 [ "This program will generate a signed TLS certificate"
45 , "using the ACME protocol and the free Let's Encrypt! CA." 51 , "using the ACME protocol and the free Let's Encrypt! CA."
46 ] 52 ]
53run :: Options -> IO ()
54run (Options (Certify opts)) = runCertify opts >>= either (error . ("Error: " ++)) return
55run (Options (Update opts)) = runUpdate opts
47 56
48data CmdOpts = CmdOpts { 57data Command = Certify CertifyOpts | Update UpdateOpts
58
59data Options = Options {
60 optCommand :: Command
61}
62
63data CertifyOpts = CertifyOpts {
49 optKeyFile :: String, 64 optKeyFile :: String,
50 optDomains :: [String], 65 optDomains :: [String],
51 optChallengeDir :: String, 66 optChallengeDir :: String,
@@ -57,6 +72,10 @@ data CmdOpts = CmdOpts {
57 optSkipProvisionCheck :: Bool 72 optSkipProvisionCheck :: Bool
58} 73}
59 74
75data UpdateOpts = UpdateOpts {
76 updateConfigFile :: Maybe FilePath
77}
78
60data AcmeCertRequest = AcmeCertRequest { 79data AcmeCertRequest = AcmeCertRequest {
61 acrDomains :: [(DomainName, HttpProvisioner)], 80 acrDomains :: [(DomainName, HttpProvisioner)],
62 acrSkipDH :: Bool, 81 acrSkipDH :: Bool,
@@ -64,51 +83,62 @@ data AcmeCertRequest = AcmeCertRequest {
64 acrUserKeys :: Keys 83 acrUserKeys :: Keys
65} 84}
66 85
67cmdopts :: Parser CmdOpts 86updateOpts :: Parser Command
68cmdopts = CmdOpts <$> strOption (long "key" <> metavar "FILE" <> 87updateOpts = fmap Update $
69 help "Filename of your private RSA key") 88 UpdateOpts <$> optional
70 <*> some 89 (strOption
71 (strOption 90 (long "config" <>
72 (long "domain" <> 91 metavar "FILENAME" <>
73 metavar "DOMAIN" <> 92 help "location of YAML configuration file"))
74 help 93
75 (unwords 94certifyOpts :: Parser Command
76 [ "The domain name(s) to certify;" 95certifyOpts = fmap Certify $
77 , "specify more than once for a multi-domain certificate" 96 CertifyOpts <$> strOption (long "key" <> metavar "FILE" <>
78 ]))) 97 help "Filename of your private RSA key")
79 <*> strOption (long "challenge-dir" <> metavar "DIR" <> 98 <*> some
80 help "Output directory for ACME challenges") 99 (strOption
81 <*> optional 100 (long "domain" <>
82 (strOption 101 metavar "DOMAIN" <>
83 (long "domain-dir" <> 102 help
84 metavar "DIR" <> 103 (unwords
85 help 104 [ "The domain name(s) to certify;"
86 (unwords 105 , "specify more than once for a multi-domain certificate"
87 [ "Directory in which to domain certificates and keys are stored;" 106 ])))
88 , "the default is to use the (first) domain name as a directory name" 107 <*> strOption (long "challenge-dir" <> metavar "DIR" <>
89 ]))) 108 help "Output directory for ACME challenges")
90 <*> optional 109 <*> optional
91 (strOption (long "email" <> metavar "ADDRESS" <> 110 (strOption
92 help "An email address with which to register an account")) 111 (long "domain-dir" <>
93 <*> optional (strOption (long "terms" <> metavar "URL" <> 112 metavar "DIR" <>
94 help "The terms param of the registration request")) 113 help
95 <*> switch 114 (unwords
96 (long "skip-dhparams" <> help "Don't generate DH params for combined cert") 115 [ "Directory in which to domain certificates and keys are stored;"
97 <*> switch 116 , "the default is to use the (first) domain name as a directory name"
98 (long "staging" <> help 117 ])))
99 (unwords 118 <*> optional (strOption (long "email" <> metavar "ADDRESS" <>
100 [ "Use staging servers instead of live servers" 119 help "An email address with which to register an account"))
101 , "(generated certificates will not be trusted!)" 120 <*> optional (strOption (long "terms" <> metavar "URL" <>
102 ])) 121 help "The terms param of the registration request"))
103 <*> switch 122 <*> switch (long "skip-dhparams" <> help "Don't generate DH params for combined cert")
104 (long "skip-provision-check" <> help 123 <*> switch
105 (unwords 124 (long "staging" <> help
106 [ "Don't test whether HTTP provisioning works before" 125 (unwords
107 , "making ACME requests" 126 [ "Use staging servers instead of live servers"
108 ])) 127 , "(generated certificates will not be trusted!)"
109 128 ]))
110go :: CmdOpts -> IO (Either String ()) 129 <*> switch
111go CmdOpts { .. } = do 130 (long "skip-provision-check" <> help
131 (unwords
132 [ "Don't test whether HTTP provisioning works before"
133 , "making ACME requests"
134 ]))
135
136runUpdate :: UpdateOpts -> IO ()
137runUpdate UpdateOpts{..} = do
138 error "test"
139
140runCertify :: CertifyOpts -> IO (Either String ())
141runCertify CertifyOpts{..} = do
112 let terms = fromMaybe defaultTerms (join $ parseAbsoluteURI <$> optTerms) 142 let terms = fromMaybe defaultTerms (join $ parseAbsoluteURI <$> optTerms)
113 directoryUrl = if optStaging then stagingDirectoryUrl else liveDirectoryUrl 143 directoryUrl = if optStaging then stagingDirectoryUrl else liveDirectoryUrl
114 domainDir = fromMaybe (head optDomains) optDomainDir 144 domainDir = fromMaybe (head optDomains) optDomainDir