forked from TrueCloudLab/lego
Add --csr option to generate a certificate for an existing CSR
This commit is contained in:
parent
8d7afd02b9
commit
333af54906
2 changed files with 68 additions and 6 deletions
4
cli.go
4
cli.go
|
@ -103,6 +103,10 @@ func main() {
|
|||
Name: "domains, d",
|
||||
Usage: "Add domains to the process",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "csr, c",
|
||||
Usage: "Certificate signing request filename, if an external CSR is to be used",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "server, s",
|
||||
Value: "https://acme-v01.api.letsencrypt.org/directory",
|
||||
|
|
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
|
@ -148,10 +149,13 @@ func saveCertRes(certRes acme.CertificateResource, conf *Configuration) {
|
|||
logger().Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error())
|
||||
}
|
||||
|
||||
if certRes.PrivateKey != nil {
|
||||
// if we were given a CSR, we don't know the private key
|
||||
err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600)
|
||||
if err != nil {
|
||||
logger().Fatalf("Unable to save PrivateKey for domain %s\n\t%s", certRes.Domain, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
jsonBytes, err := json.MarshalIndent(certRes, "", "\t")
|
||||
if err != nil {
|
||||
|
@ -205,6 +209,36 @@ func handleTOS(c *cli.Context, client *acme.Client, acc *Account) {
|
|||
}
|
||||
}
|
||||
|
||||
func readCSRFile(filename string) ([]byte, error) {
|
||||
bytes, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// see if we can find a PEM-encoded CSR
|
||||
var p *pem.Block
|
||||
rest := bytes
|
||||
for {
|
||||
// decode a PEM block
|
||||
p, rest = pem.Decode(rest)
|
||||
|
||||
// did we fail?
|
||||
if p == nil {
|
||||
break
|
||||
}
|
||||
|
||||
// did we get a CSR?
|
||||
if p.Type == "CERTIFICATE REQUEST" {
|
||||
return p.Bytes, nil
|
||||
}
|
||||
}
|
||||
|
||||
// no PEM-encoded CSR
|
||||
// assume we were given a DER-encoded ASN.1 CSR
|
||||
// (if this assumption is wrong, parsing these bytes will fail)
|
||||
return bytes, nil
|
||||
}
|
||||
|
||||
func run(c *cli.Context) error {
|
||||
conf, acc, client := setup(c)
|
||||
if acc.Registration == nil {
|
||||
|
@ -232,11 +266,35 @@ func run(c *cli.Context) error {
|
|||
handleTOS(c, client, acc)
|
||||
}
|
||||
|
||||
if len(c.GlobalStringSlice("domains")) == 0 {
|
||||
logger().Fatal("Please specify --domains or -d")
|
||||
// we require either domains or csr, but not both
|
||||
hasDomains := len(c.GlobalStringSlice("domains")) > 0
|
||||
hasCsr := len(c.GlobalString("csr")) > 0
|
||||
if hasDomains && hasCsr {
|
||||
logger().Fatal("Please specify either --domains/-d or --csr/-c, but not both")
|
||||
}
|
||||
if !hasDomains && !hasCsr {
|
||||
logger().Fatal("Please specify --domains/-d (or --csr/-c if you already have a CSR)")
|
||||
}
|
||||
|
||||
cert, failures := client.ObtainCertificate(c.GlobalStringSlice("domains"), !c.Bool("no-bundle"), nil)
|
||||
var cert acme.CertificateResource
|
||||
var failures map[string]error
|
||||
|
||||
if hasDomains {
|
||||
// obtain a certificate, generating a new private key
|
||||
cert, failures = client.ObtainCertificate(c.GlobalStringSlice("domains"), true, nil)
|
||||
} else {
|
||||
// read the CSR
|
||||
csr, err := readCSRFile(c.GlobalString("csr"))
|
||||
if err != nil {
|
||||
// we couldn't read the CSR
|
||||
failures = map[string]error{"csr": err}
|
||||
} else {
|
||||
// obtain a certificate for this CSR
|
||||
cert, failures = client.ObtainCertificateForCSR(csr, true)
|
||||
}
|
||||
}
|
||||
|
||||
cert, failures = client.ObtainCertificate(c.GlobalStringSlice("domains"), !c.Bool("no-bundle"), nil)
|
||||
if len(failures) > 0 {
|
||||
for k, v := range failures {
|
||||
logger().Printf("[%s] Could not obtain certificates\n\t%s", k, v.Error())
|
||||
|
|
Loading…
Reference in a new issue