forked from TrueCloudLab/lego
Informations about renewed certificates are now passed to the renew hook (#1108)
This commit is contained in:
parent
3213540c52
commit
7a61e681b0
3 changed files with 55 additions and 14 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue