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",
|
Name: "domains, d",
|
||||||
Usage: "Add domains to the process",
|
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{
|
cli.StringFlag{
|
||||||
Name: "server, s",
|
Name: "server, s",
|
||||||
Value: "https://acme-v01.api.letsencrypt.org/directory",
|
Value: "https://acme-v01.api.letsencrypt.org/directory",
|
||||||
|
|
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"encoding/pem"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
@ -148,9 +149,12 @@ func saveCertRes(certRes acme.CertificateResource, conf *Configuration) {
|
||||||
logger().Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error())
|
logger().Fatalf("Unable to save Certificate for domain %s\n\t%s", certRes.Domain, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ioutil.WriteFile(privOut, certRes.PrivateKey, 0600)
|
if certRes.PrivateKey != nil {
|
||||||
if err != nil {
|
// if we were given a CSR, we don't know the private key
|
||||||
logger().Fatalf("Unable to save PrivateKey for domain %s\n\t%s", certRes.Domain, err.Error())
|
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")
|
jsonBytes, err := json.MarshalIndent(certRes, "", "\t")
|
||||||
|
@ -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 {
|
func run(c *cli.Context) error {
|
||||||
conf, acc, client := setup(c)
|
conf, acc, client := setup(c)
|
||||||
if acc.Registration == nil {
|
if acc.Registration == nil {
|
||||||
|
@ -232,11 +266,35 @@ func run(c *cli.Context) error {
|
||||||
handleTOS(c, client, acc)
|
handleTOS(c, client, acc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.GlobalStringSlice("domains")) == 0 {
|
// we require either domains or csr, but not both
|
||||||
logger().Fatal("Please specify --domains or -d")
|
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 {
|
if len(failures) > 0 {
|
||||||
for k, v := range failures {
|
for k, v := range failures {
|
||||||
logger().Printf("[%s] Could not obtain certificates\n\t%s", k, v.Error())
|
logger().Printf("[%s] Could not obtain certificates\n\t%s", k, v.Error())
|
||||||
|
|
Loading…
Reference in a new issue