forked from TrueCloudLab/lego
Adds renew hook (#845)
* chore: update golangci-lint. * feat: support renew-hook.
This commit is contained in:
parent
55572c2606
commit
5d557fdc6d
6 changed files with 48 additions and 15 deletions
|
@ -32,7 +32,7 @@ before_install:
|
||||||
- go get -u github.com/letsencrypt/pebble/...
|
- go get -u github.com/letsencrypt/pebble/...
|
||||||
|
|
||||||
# Install linters and misspell
|
# Install linters and misspell
|
||||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.15.0
|
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s -- -b $GOPATH/bin v1.16.0
|
||||||
- golangci-lint --version
|
- golangci-lint --version
|
||||||
|
|
||||||
# Hugo - documentation
|
# Hugo - documentation
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-acme/lego/acme/api/internal/nonces"
|
"github.com/go-acme/lego/acme/api/internal/nonces"
|
||||||
|
@ -118,9 +117,6 @@ func (j *JWS) GetKeyAuthorization(token string) (string, error) {
|
||||||
|
|
||||||
// Generate the Key Authorization for the challenge
|
// Generate the Key Authorization for the challenge
|
||||||
jwk := &jose.JSONWebKey{Key: publicKey}
|
jwk := &jose.JSONWebKey{Key: publicKey}
|
||||||
if jwk == nil {
|
|
||||||
return "", errors.New("could not generate JWK from key")
|
|
||||||
}
|
|
||||||
|
|
||||||
thumbBytes, err := jwk.Thumbprint(crypto.SHA256)
|
thumbBytes, err := jwk.Thumbprint(crypto.SHA256)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-acme/lego/certcrypto"
|
"github.com/go-acme/lego/certcrypto"
|
||||||
|
@ -47,6 +52,10 @@ func createRenew() cli.Command {
|
||||||
Name: "must-staple",
|
Name: "must-staple",
|
||||||
Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.",
|
Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.",
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "renew-hook",
|
||||||
|
Usage: "Define a hook. The hook is executed only when the certificates are effectively renewed.",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +131,7 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
|
||||||
|
|
||||||
certsStorage.SaveResource(certRes)
|
certsStorage.SaveResource(certRes)
|
||||||
|
|
||||||
return nil
|
return renewHook(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
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) error {
|
||||||
|
@ -158,8 +167,7 @@ func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *Certificat
|
||||||
|
|
||||||
certsStorage.SaveResource(certRes)
|
certsStorage.SaveResource(certRes)
|
||||||
|
|
||||||
return nil
|
return renewHook(ctx)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool {
|
func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool {
|
||||||
|
@ -194,3 +202,25 @@ func merge(prevDomains []string, nextDomains []string) []string {
|
||||||
}
|
}
|
||||||
return prevDomains
|
return prevDomains
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renewHook(ctx *cli.Context) error {
|
||||||
|
hook := ctx.String("renew-hook")
|
||||||
|
if hook == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxCmd, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
parts := strings.Fields(hook)
|
||||||
|
output, err := exec.CommandContext(ctxCmd, parts[0], parts[1:]...).CombinedOutput()
|
||||||
|
if len(output) > 0 {
|
||||||
|
fmt.Println(string(output))
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctxCmd.Err() == context.DeadlineExceeded {
|
||||||
|
return errors.New("hook timed out")
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,14 @@ lego --email="foo@bar.com" --domains="example.com" --http renew
|
||||||
lego --email="foo@bar.com" --domains="example.com" --http renew --days 45
|
lego --email="foo@bar.com" --domains="example.com" --http renew --days 45
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### To renew the certificate (and hook)
|
||||||
|
|
||||||
|
The hook is executed only when the certificates are effectively renewed.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
lego --email="foo@bar.com" --domains="example.com" --http renew --renew-hook="./myscript.sh"
|
||||||
|
```
|
||||||
|
|
||||||
### Obtain a certificate using the DNS challenge
|
### Obtain a certificate using the DNS challenge
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -132,5 +132,4 @@ func generateCLIHelp(models *Providers) error {
|
||||||
|
|
||||||
_, err = file.Write(source)
|
_, err = file.Write(source)
|
||||||
return err
|
return err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,13 +47,13 @@ func (d *DNSProvider) addTXTRecord(domain string, name string, value string, ttl
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
message := &apiResponse{}
|
message := apiResponse{}
|
||||||
err = d.do(req, message)
|
err = d.do(req, &message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to create TXT record for domain %s and name %s: %v", domain, name, err)
|
return fmt.Errorf("unable to create TXT record for domain %s and name %s: %v", domain, name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if message != nil && len(message.Message) > 0 {
|
if len(message.Message) > 0 {
|
||||||
log.Infof("API response: %s", message.Message)
|
log.Infof("API response: %s", message.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,13 +87,13 @@ func (d *DNSProvider) deleteTXTRecord(domain string, name string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
message := &apiResponse{}
|
message := apiResponse{}
|
||||||
err = d.do(req, message)
|
err = d.do(req, &message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to delete TXT record for domain %s and name %s: %v", domain, name, err)
|
return fmt.Errorf("unable to delete TXT record for domain %s and name %s: %v", domain, name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if message != nil && len(message.Message) > 0 {
|
if len(message.Message) > 0 {
|
||||||
log.Infof("API response: %s", message.Message)
|
log.Infof("API response: %s", message.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue