Files
certman/server.go

166 lines
4.2 KiB
Go

package main
import (
"fmt"
"log"
"path/filepath"
"sync"
"time"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5/storage/memory"
)
var (
tickMu sync.Mutex
mgr *ACMEManager
mgrMu sync.Mutex
)
func getACMEManager() (*ACMEManager, error) {
mgrMu.Lock()
defer mgrMu.Unlock()
if mgr == nil {
var err error
mgr, err = NewACMEManager()
if err != nil {
return nil, err
}
}
return mgr, nil
}
func initServer() {
err := LoadDomainConfigs()
if err != nil {
log.Fatalf("Error loading domain configs: %v", err)
}
serverTick()
}
func serverTick() {
tickMu.Lock()
defer tickMu.Unlock()
fmt.Println("Tick!")
mgr, err := getACMEManager()
if err != nil {
fmt.Printf("Error getting acme manager: %v\n", err)
return
}
now := time.Now().UTC()
localDomainConfigs := domainStore.Snapshot()
for domainStr, domainConfig := range localDomainConfigs {
if !domainConfig.GetBool("Domain.enabled") {
continue
}
renewPeriod := domainConfig.GetInt("Certificates.renew_period")
lastIssued := time.Unix(domainConfig.GetInt64("Internal.last_issued"), 0).UTC()
renewalDue := lastIssued.AddDate(0, 0, renewPeriod)
if now.After(renewalDue) {
//TODO extra check if certificate expiry (create cache?)
_, err = mgr.RenewForDomain(domainStr)
if err != nil {
// if no existing cert, obtain instead
_, err = mgr.ObtainForDomain(domainStr)
if err != nil {
fmt.Printf("Error obtaining domain certificates for domain %s: %v\n", domainStr, err)
continue
}
}
domainConfig.Set("Internal.last_issued", time.Now().UTC().Unix())
err = WriteDomainConfig(domainConfig)
if err != nil {
fmt.Printf("Error saving domain config %s: %v\n", domainStr, err)
continue
}
err = EncryptFileXChaCha(domainConfig.GetString("Certificates.crypto_key"), filepath.Join(mgr.certsRoot, domainStr, domainStr+".crt"), filepath.Join(mgr.certsRoot, domainStr, domainStr+".crt.crpt"), nil)
if err != nil {
fmt.Printf("Error encrypting domain cert for domain %s: %v\n", domainStr, err)
continue
}
err = EncryptFileXChaCha(domainConfig.GetString("Certificates.crypto_key"), filepath.Join(mgr.certsRoot, domainStr, domainStr+".key"), filepath.Join(mgr.certsRoot, domainStr, domainStr+".key.crpt"), nil)
if err != nil {
fmt.Printf("Error encrypting domain key for domain %s: %v\n", domainStr, err)
continue
}
giteaClient := createGiteaClient()
if giteaClient == nil {
fmt.Printf("Error creating gitea client for domain %s: %v\n", domainStr, err)
continue
}
gitWorkspace := &GitWorkspace{
Storage: memory.NewStorage(),
FS: memfs.New(),
}
var repoUrl string
if !domainConfig.GetBool("Internal.repo_exists") {
repoUrl = createGiteaRepo(domainStr, giteaClient)
if repoUrl == "" {
fmt.Printf("Error creating Gitea repo for domain %s\n", domainStr)
continue
}
domainConfig.Set("Internal.repo_exists", true)
err = WriteDomainConfig(domainConfig)
if err != nil {
fmt.Printf("Error saving domain config %s: %v\n", domainStr, err)
continue
}
err = initRepo(repoUrl, gitWorkspace)
if err != nil {
fmt.Printf("Error initializing repo for domain %s: %v\n", domainStr, err)
continue
}
} else {
repoUrl = config.GetString("Git.server") + "/" + config.GetString("Git.org_name") + "/" + domainStr + domainConfig.GetString("Repo.repo_suffix") + ".git"
err = cloneRepo(repoUrl, gitWorkspace)
if err != nil {
fmt.Printf("Error cloning repo for domain %s: %v\n", domainStr, err)
continue
}
}
err = addAndPushCerts(domainStr, gitWorkspace)
if err != nil {
fmt.Printf("Error pushing certificates for domain %s: %v\n", domainStr, err)
continue
}
fmt.Printf("Successfully pushed certificates for domain %s\n", domainStr)
}
}
err = SaveDomainConfigs()
if err != nil {
fmt.Printf("Error saving domain configs: %v\n", err)
}
}
func reloadServer() {
fmt.Println("Reloading configs...")
err := LoadDomainConfigs()
if err != nil {
fmt.Printf("Error loading domain configs: %v\n", err)
return
}
mgrMu.Lock()
mgr = nil
mgrMu.Unlock()
fmt.Println("Successfully reloaded configs")
}
func stopServer() {
fmt.Println("Shutting down server")
}