@@ -236,13 +236,16 @@ let
236236
237237 # Create hashes for cert data directories based on configuration
238238 # Flags are separated to avoid collisions
239- hashData = with builtins ; ''
240- ${ lib . concatStringsSep " " data . extraLegoFlags } -
241- ${ lib . concatStringsSep " " data . extraLegoRunFlags } -
242- ${ lib . concatStringsSep " " data . extraLegoRenewFlags } -
243- ${ toString acmeServer } ${ toString data . dnsProvider }
244- ${ toString data . ocspMustStaple } ${ data . keyType }
245- '' ;
239+ hashData =
240+ with builtins ;
241+ ''
242+ ${ lib . concatStringsSep " " data . extraLegoFlags } -
243+ ${ lib . concatStringsSep " " data . extraLegoRunFlags } -
244+ ${ lib . concatStringsSep " " data . extraLegoRenewFlags } -
245+ ${ toString acmeServer } ${ toString data . dnsProvider }
246+ ${ toString data . ocspMustStaple } ${ data . keyType }
247+ ''
248+ + ( lib . optionalString ( data . csr != null ) ( " - " + data . csr ) ) ;
246249 certDir = mkHash hashData ;
247250 # TODO remove domainHash usage entirely. Waiting on go-acme/lego#1532
248251 domainHash = mkHash "${ lib . concatStringsSep " " extraDomains } ${ data . domain } " ;
@@ -286,18 +289,24 @@ let
286289 "--accept-tos" # Checking the option is covered by the assertions
287290 "--path"
288291 "."
289- "-d"
290- data . domain
291292 "--email"
292293 data . email
293- "--key-type"
294- data . keyType
295294 ]
296295 ++ protocolOpts
297296 ++ lib . optionals ( acmeServer != null ) [
298297 "--server"
299298 acmeServer
300299 ]
300+ ++ lib . optionals ( data . csr != null ) [
301+ "--csr"
302+ data . csr
303+ ]
304+ ++ lib . optionals ( data . csr == null ) [
305+ "--key-type"
306+ data . keyType
307+ "-d"
308+ data . domain
309+ ]
301310 ++ lib . concatMap ( name : [
302311 "-d"
303312 name
327336 webroots = lib . remove null (
328337 lib . unique ( builtins . map ( certAttrs : certAttrs . webroot ) ( lib . attrValues config . security . acme . certs ) )
329338 ) ;
339+
340+ certificateKey = if data . csrKey != null then "${ data . csrKey } " else "certificates/${ keyName } .key" ;
330341 in
331342 {
332343 inherit accountHash cert selfsignedDeps ;
529540 # Check if we can renew.
530541 # We can only renew if the list of domains has not changed.
531542 # We also need an account key. Avoids #190493
532- if cmp -s domainhash.txt certificates/domainhash.txt && [ -e 'certificates/ ${ keyName } .key ' ] && [ -e 'certificates/${ keyName } .crt' ] && [ -n "$(find accounts -name '${ data . email } .key')" ]; then
543+ if cmp -s domainhash.txt certificates/domainhash.txt && [ -e '${ certificateKey } ' ] && [ -e 'certificates/${ keyName } .crt' ] && [ -n "$(find accounts -name '${ data . email } .key')" ]; then
533544
534545 # Even if a cert is not expired, it may be revoked by the CA.
535546 # Try to renew, and silently fail if the cert is not expired.
564575 touch out/renewed
565576 echo Installing new certificate
566577 cp -vp 'certificates/${ keyName } .crt' out/fullchain.pem
567- cp -vp 'certificates/ ${ keyName } .key ' out/key.pem
578+ cp -vp '${ certificateKey } ' out/key.pem
568579 cp -vp 'certificates/${ keyName } .issuer.crt' out/chain.pem
569580 ln -sf fullchain.pem out/cert.pem
570581 cat out/key.pem out/fullchain.pem > out/full.pem
845856 description = "Domain to fetch certificate for (defaults to the entry name)." ;
846857 } ;
847858
859+ csr = lib . mkOption {
860+ type = lib . types . nullOr lib . types . str ;
861+ default = null ;
862+ description = "Path to a certificate signing request to apply when fetching the certificate." ;
863+ } ;
864+
865+ csrKey = lib . mkOption {
866+ type = lib . types . nullOr lib . types . str ;
867+ default = null ;
868+ description = "Path to the private key to the matching certificate signing request." ;
869+ } ;
870+
848871 extraDomainNames = lib . mkOption {
849872 type = lib . types . listOf lib . types . str ;
850873 default = [ ] ;
@@ -1113,6 +1136,17 @@ in
11131136 used for variables suffixed by "_FILE".
11141137 '' ;
11151138 }
1139+
1140+ {
1141+ assertion = lib . all (
1142+ certOpts :
1143+ ( certOpts . csr == null && certOpts . csrKey == null )
1144+ || ( certOpts . csr != null && certOpts . csrKey != null )
1145+ ) certs ;
1146+ message = ''
1147+ When passing a certificate signing request both `security.acme.certs.${ cert } .csr` and `security.acme.certs.${ cert } .csrKey` need to be set.
1148+ '' ;
1149+ }
11161150 ] ) cfg . certs
11171151 ) ) ;
11181152
0 commit comments