Informations about renewed certificates are now passed to the renew hook (#1108)

This commit is contained in:
sdlspr 2020-04-11 14:57:06 +02:00 committed by GitHub
parent 3213540c52
commit 7a61e681b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 14 deletions

View file

@ -133,8 +133,7 @@ func (s *CertificatesStorage) ReadResource(domain string) certificate.Resource {
} }
func (s *CertificatesStorage) ExistsFile(domain, extension string) bool { func (s *CertificatesStorage) ExistsFile(domain, extension string) bool {
filename := sanitizedDomain(domain) + extension filePath := s.GetFileName(domain, extension)
filePath := filepath.Join(s.rootPath, filename)
if _, err := os.Stat(filePath); os.IsNotExist(err) { if _, err := os.Stat(filePath); os.IsNotExist(err) {
return false return false
@ -145,10 +144,12 @@ func (s *CertificatesStorage) ExistsFile(domain, extension string) bool {
} }
func (s *CertificatesStorage) ReadFile(domain, extension string) ([]byte, error) { func (s *CertificatesStorage) ReadFile(domain, extension string) ([]byte, error) {
filename := sanitizedDomain(domain) + extension return ioutil.ReadFile(s.GetFileName(domain, extension))
filePath := filepath.Join(s.rootPath, filename) }
return ioutil.ReadFile(filePath) func (s *CertificatesStorage) GetFileName(domain, extension string) string {
filename := sanitizedDomain(domain) + extension
return filepath.Join(s.rootPath, filename)
} }
func (s *CertificatesStorage) ReadCertificate(domain, extension string) ([]*x509.Certificate, error) { func (s *CertificatesStorage) ReadCertificate(domain, extension string) ([]*x509.Certificate, error) {

View file

@ -6,6 +6,7 @@ import (
"crypto/x509" "crypto/x509"
"errors" "errors"
"fmt" "fmt"
"os"
"os/exec" "os/exec"
"strings" "strings"
"time" "time"
@ -17,6 +18,13 @@ import (
"github.com/urfave/cli" "github.com/urfave/cli"
) )
const (
renewEnvAccountEmail = "LEGO_ACCOUNT_EMAIL"
renewEnvCertDomain = "LEGO_CERT_DOMAIN"
renewEnvCertPath = "LEGO_CERT_PATH"
renewEnvCertKeyPath = "LEGO_CERT_KEY_PATH"
)
func createRenew() cli.Command { func createRenew() cli.Command {
return cli.Command{ return cli.Command{
Name: "renew", Name: "renew",
@ -72,16 +80,18 @@ func renew(ctx *cli.Context) error {
bundle := !ctx.Bool("no-bundle") bundle := !ctx.Bool("no-bundle")
meta := map[string]string{renewEnvAccountEmail: account.Email}
// CSR // CSR
if ctx.GlobalIsSet("csr") { if ctx.GlobalIsSet("csr") {
return renewForCSR(ctx, client, certsStorage, bundle) return renewForCSR(ctx, client, certsStorage, bundle, meta)
} }
// Domains // Domains
return renewForDomains(ctx, client, certsStorage, bundle) return renewForDomains(ctx, client, certsStorage, bundle, meta)
} }
func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool) error { func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error {
domains := ctx.GlobalStringSlice("domains") domains := ctx.GlobalStringSlice("domains")
domain := domains[0] domain := domains[0]
@ -131,10 +141,14 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
certsStorage.SaveResource(certRes) certsStorage.SaveResource(certRes)
return renewHook(ctx) meta[renewEnvCertDomain] = domain
meta[renewEnvCertPath] = certsStorage.GetFileName(domain, "crt")
meta[renewEnvCertKeyPath] = certsStorage.GetFileName(domain, "key")
return renewHook(ctx, meta)
} }
func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool) error { func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error {
csr, err := readCSRFile(ctx.GlobalString("csr")) csr, err := readCSRFile(ctx.GlobalString("csr"))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -167,7 +181,11 @@ func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *Certificat
certsStorage.SaveResource(certRes) certsStorage.SaveResource(certRes)
return renewHook(ctx) meta[renewEnvCertDomain] = domain
meta[renewEnvCertPath] = certsStorage.GetFileName(domain, "crt")
meta[renewEnvCertKeyPath] = certsStorage.GetFileName(domain, "key")
return renewHook(ctx, meta)
} }
func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool { func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool {
@ -203,17 +221,22 @@ func merge(prevDomains []string, nextDomains []string) []string {
return prevDomains return prevDomains
} }
func renewHook(ctx *cli.Context) error { func renewHook(ctx *cli.Context, meta map[string]string) error {
hook := ctx.String("renew-hook") hook := ctx.String("renew-hook")
if hook == "" { if hook == "" {
return nil return nil
} }
ctxCmd, cancel := context.WithTimeout(context.Background(), 30*time.Second) ctxCmd, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel() defer cancel()
parts := strings.Fields(hook) parts := strings.Fields(hook)
output, err := exec.CommandContext(ctxCmd, parts[0], parts[1:]...).CombinedOutput()
cmdCtx := exec.CommandContext(ctxCmd, parts[0], parts[1:]...)
cmdCtx.Env = append(os.Environ(), metaToEnv(meta)...)
output, err := cmdCtx.CombinedOutput()
if len(output) > 0 { if len(output) > 0 {
fmt.Println(string(output)) fmt.Println(string(output))
} }
@ -224,3 +247,13 @@ func renewHook(ctx *cli.Context) error {
return err return err
} }
func metaToEnv(meta map[string]string) []string {
var envs []string
for k, v := range meta {
envs = append(envs, k+"="+v)
}
return envs
}

View file

@ -38,6 +38,13 @@ The hook is executed only when the certificates are effectively renewed.
lego --email="foo@bar.com" --domains="example.com" --http renew --renew-hook="./myscript.sh" lego --email="foo@bar.com" --domains="example.com" --http renew --renew-hook="./myscript.sh"
``` ```
Some information are added to the environment variables when the hook is used:
- `LEGO_ACCOUNT_EMAIL`: the email of the account.
- `LEGO_CERT_DOMAIN`: the main domain of the certificate.
- `LEGO_CERT_PATH`: the path of the certificate.
- `LEGO_CERT_KEY_PATH`: the path of the certificate key.
### Obtain a certificate using the DNS challenge ### Obtain a certificate using the DNS challenge
```bash ```bash