mirror of
https://github.com/InazumaV/Ratte.git
synced 2026-02-04 04:30:09 +00:00
120 lines
2.8 KiB
Go
120 lines
2.8 KiB
Go
package acme
|
|
|
|
import (
|
|
"Ratte/common/file"
|
|
"fmt"
|
|
"github.com/go-acme/lego/v4/certcrypto"
|
|
"github.com/go-acme/lego/v4/certificate"
|
|
"github.com/go-acme/lego/v4/challenge/http01"
|
|
"github.com/go-acme/lego/v4/providers/dns"
|
|
"os"
|
|
"path"
|
|
"time"
|
|
)
|
|
|
|
func checkPath(p string) error {
|
|
if !file.IsExist(path.Dir(p)) {
|
|
err := os.MkdirAll(path.Dir(p), 0755)
|
|
if err != nil {
|
|
return fmt.Errorf("create dir error: %s", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (l *Acme) SetProvider() error {
|
|
switch l.c.Provider {
|
|
case "http":
|
|
err := l.client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "80"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case "dns":
|
|
for k, v := range l.c.DNSEnv {
|
|
os.Setenv(k, v)
|
|
}
|
|
p, err := dns.NewDNSChallengeProviderByName(l.c.Provider)
|
|
if err != nil {
|
|
return fmt.Errorf("create dns challenge provider error: %s", err)
|
|
}
|
|
err = l.client.Challenge.SetDNS01Provider(p)
|
|
if err != nil {
|
|
return fmt.Errorf("set dns provider error: %s", err)
|
|
}
|
|
default:
|
|
return fmt.Errorf("unsupported provider %s", l.c.Provider)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (l *Acme) CreateCert(certPath, keyPath, domain string) (err error) {
|
|
if certPath == "" || keyPath == "" {
|
|
return fmt.Errorf("cert file path or key file path not exist")
|
|
}
|
|
if file.IsExist(certPath) && file.IsExist(keyPath) {
|
|
return l.RenewCert(certPath, keyPath, domain)
|
|
}
|
|
request := certificate.ObtainRequest{
|
|
Domains: []string{domain},
|
|
Bundle: true,
|
|
}
|
|
certificates, err := l.client.Certificate.Obtain(request)
|
|
if err != nil {
|
|
return fmt.Errorf("obtain certificate error: %s", err)
|
|
}
|
|
err = l.writeCert(certPath, keyPath, certificates)
|
|
return nil
|
|
}
|
|
|
|
func (l *Acme) RenewCert(certPath, keyPath, domain string) error {
|
|
file, err := os.ReadFile(certPath)
|
|
if err != nil {
|
|
return fmt.Errorf("read cert file error: %s", err)
|
|
}
|
|
if e, err := l.CheckCert(file); !e {
|
|
return nil
|
|
} else if err != nil {
|
|
return fmt.Errorf("check cert error: %s", err)
|
|
}
|
|
res, err := l.client.Certificate.Renew(certificate.Resource{
|
|
Domain: domain,
|
|
Certificate: file,
|
|
}, true, false, "")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = l.writeCert(certPath, keyPath, res)
|
|
return nil
|
|
}
|
|
|
|
func (l *Acme) CheckCert(file []byte) (bool, error) {
|
|
cert, err := certcrypto.ParsePEMCertificate(file)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
notAfter := int(time.Until(cert.NotAfter).Hours() / 24.0)
|
|
if notAfter > 30 {
|
|
return false, nil
|
|
}
|
|
return true, nil
|
|
}
|
|
func (l *Acme) writeCert(cert, key string, certificates *certificate.Resource) error {
|
|
err := checkPath(cert)
|
|
if err != nil {
|
|
return fmt.Errorf("check path error: %s", err)
|
|
}
|
|
err = os.WriteFile(cert, certificates.Certificate, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = checkPath(key)
|
|
if err != nil {
|
|
return fmt.Errorf("check path error: %s", err)
|
|
}
|
|
err = os.WriteFile(key, certificates.PrivateKey, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|