Added first acme implementation

This commit is contained in:
Pablu23
2025-07-20 18:34:20 +02:00
parent dc2fe84a96
commit 77a880cee1
8 changed files with 591 additions and 386 deletions

111
acme/acme.go Normal file
View File

@@ -0,0 +1,111 @@
package acme
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"net/http"
"os"
"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/challenge/tlsalpn01"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration"
domainrouter "github.com/pablu23/domain-router"
)
func SetupAcme(config *domainrouter.Config) 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
}
err = os.WriteFile(acme.KeyFile, []byte(encode(privateKey)), 0666)
if err != nil {
return err
}
} else {
keyBytes, err := os.ReadFile(acme.KeyFile)
if err != nil {
return err
}
privateKey = decode(string(keyBytes))
}
user := User{
Email: acme.Email,
key: privateKey,
}
leConfig := lego.NewConfig(&user)
leConfig.CADirURL = acme.CADirURL
leConfig.Certificate.KeyType = certcrypto.RSA2048
leConfig.HTTPClient.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client, err := lego.NewClient(leConfig)
if err != nil {
return err
}
// strconv.Itoa(config.Server.Port)
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "5002"))
if err != nil {
return err
}
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "5001"))
if err != nil {
return err
}
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
return err
}
user.Registration = reg
domains := make([]string, 0)
for _, host := range config.Hosts {
domains = append(domains, host.Domains...)
}
request := certificate.ObtainRequest{
Domains: domains,
Bundle: true,
}
certificates, err := client.Certificate.Obtain(request)
if err != nil {
return err
}
fmt.Printf("%#v\n", certificates)
return nil
}
func encode(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 {
block, _ := pem.Decode([]byte(pemEncoded))
x509Encoded := block.Bytes
privateKey, _ := x509.ParseECPrivateKey(x509Encoded)
return privateKey
}

25
acme/user.go Normal file
View File

@@ -0,0 +1,25 @@
package acme
import (
"crypto"
"github.com/go-acme/lego/v4/registration"
)
type User struct {
Email string
Registration *registration.Resource
key crypto.PrivateKey
}
func (u *User) GetEmail() string {
return u.Email
}
func (u *User) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *User) GetPrivateKey() crypto.PrivateKey {
return u.key
}