Add renew to acme

This commit is contained in:
Pablu23
2025-07-20 22:08:32 +02:00
parent 77a880cee1
commit 21e28fb60b
4 changed files with 94 additions and 23 deletions

View File

@@ -8,9 +8,9 @@ import (
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"net/http"
"os"
"time"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
@@ -21,25 +21,33 @@ import (
domainrouter "github.com/pablu23/domain-router"
)
func SetupAcme(config *domainrouter.Config) error {
acme := config.Server.Ssl.Acme
type Acme struct {
user *User
client *lego.Client
domains []string
certFilePath string
keyFilePath string
renewTicker *time.Ticker
}
func SetupAcme(config *domainrouter.Config) (*Acme, error) {
acme := config.Server.Ssl.Acme
var privateKey *ecdsa.PrivateKey
if _, err := os.Stat(acme.KeyFile); errors.Is(err, os.ErrNotExist) {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return err
return nil, err
}
err = os.WriteFile(acme.KeyFile, []byte(encode(privateKey)), 0666)
err = os.WriteFile(acme.KeyFile, []byte(encodePrivKey(privateKey)), 0666)
if err != nil {
return err
return nil, err
}
} else {
keyBytes, err := os.ReadFile(acme.KeyFile)
if err != nil {
return err
return nil, err
}
privateKey = decode(string(keyBytes))
privateKey = decodePrivKey(string(keyBytes))
}
user := User{
@@ -56,23 +64,23 @@ func SetupAcme(config *domainrouter.Config) error {
client, err := lego.NewClient(leConfig)
if err != nil {
return err
return nil, err
}
// strconv.Itoa(config.Server.Port)
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "5002"))
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", acme.Http01Port))
if err != nil {
return err
return nil, err
}
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "5001"))
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", acme.TlsAlpn01Port))
if err != nil {
return err
return nil, err
}
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
return err
return nil, err
}
user.Registration = reg
@@ -87,22 +95,76 @@ func SetupAcme(config *domainrouter.Config) error {
}
certificates, err := client.Certificate.Obtain(request)
if err != nil {
return nil, err
}
err = os.WriteFile(config.Server.Ssl.CertFile, certificates.Certificate, 0666)
if err != nil {
return nil, err
}
err = os.WriteFile(config.Server.Ssl.KeyFile, certificates.PrivateKey, 0666)
if err != nil {
return nil, err
}
d, err := time.ParseDuration(acme.RenewTime)
if err != nil {
return nil, err
}
return &Acme{
user: &user,
client: client,
domains: domains,
certFilePath: config.Server.Ssl.CertFile,
keyFilePath: config.Server.Ssl.KeyFile,
renewTicker: time.NewTicker(d),
}, nil
}
func (a *Acme) RenewAcme() error {
request := certificate.ObtainRequest{
Domains: a.domains,
Bundle: true,
}
certificates, err := a.client.Certificate.Obtain(request)
if err != nil {
return err
}
err = os.WriteFile(a.certFilePath, certificates.Certificate, 0666)
if err != nil {
return err
}
err = os.WriteFile(a.keyFilePath, certificates.PrivateKey, 0666)
if err != nil {
return err
}
fmt.Printf("%#v\n", certificates)
return nil
}
func encode(privateKey *ecdsa.PrivateKey) string {
func (a *Acme) RegisterTicker() {
for {
select {
case <-a.renewTicker.C:
a.RenewAcme()
}
}
}
func encodePrivKey(privateKey *ecdsa.PrivateKey) string {
x509Encoded, _ := x509.MarshalECPrivateKey(privateKey)
pemEncoded := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: x509Encoded})
return string(pemEncoded)
}
func decode(pemEncoded string) *ecdsa.PrivateKey {
func decodePrivKey(pemEncoded string) *ecdsa.PrivateKey {
block, _ := pem.Decode([]byte(pemEncoded))
x509Encoded := block.Bytes
privateKey, _ := x509.ParseECPrivateKey(x509Encoded)

View File

@@ -70,12 +70,15 @@ func main() {
}
if config.Server.Ssl.Acme.Enabled {
err := acme.SetupAcme(config)
acmeRenewer, err := acme.SetupAcme(config)
if err != nil {
log.Fatal().Err(err).Msg("unable to setup acme")
}
}
go func() {
acmeRenewer.RegisterTicker()
}()
}
log.Info().Int("port", config.Server.Port).Str("cert", config.Server.Ssl.CertFile).Str("key", config.Server.Ssl.KeyFile).Msg("Starting server")
err := server.ListenAndServeTLS("", "")
log.Fatal().Err(err).Str("cert", config.Server.Ssl.CertFile).Str("key", config.Server.Ssl.KeyFile).Int("port", config.Server.Port).Msg("Could not start server")

View File

@@ -12,10 +12,13 @@ type Config struct {
CertFile string `yaml:"certFile"`
KeyFile string `yaml:"keyFile"`
Acme struct {
Enabled bool `yaml:"enabled"`
Email string `yaml:"email"`
KeyFile string `yaml:"keyFile"`
CADirURL string `yaml:"caDirUrl"`
Enabled bool `yaml:"enabled"`
Email string `yaml:"email"`
KeyFile string `yaml:"keyFile"`
CADirURL string `yaml:"caDirUrl"`
Http01Port string `yaml:"http01Port"`
TlsAlpn01Port string `yaml:"tlsAlpn01Port"`
RenewTime string `yaml:"renewTime"`
} `yaml:"acme"`
} `yaml:"ssl"`
} `yaml:"server"`

View File

@@ -9,6 +9,9 @@ server:
email: me@pablu.de
keyFile: userKey.key
caDirUrl: https://192.168.2.154:14000/dir
tlsAlpn01Port: 5001
http01Port: 5002
renewTime: 30s
logging: