package server import ( "fmt" "log" "path/filepath" "sync" "time" "git.nevets.tech/Keys/CertManager/internal" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5/storage/memory" ) var ( tickMu sync.Mutex mgr *internal.ACMEManager mgrMu sync.Mutex ) func getACMEManager() (*internal.ACMEManager, error) { mgrMu.Lock() defer mgrMu.Unlock() if mgr == nil { var err error mgr, err = internal.NewACMEManager() if err != nil { return nil, err } } return mgr, nil } func Init() { err := internal.LoadDomainConfigs() if err != nil { log.Fatalf("Error loading domain configs: %v", err) } Tick() } func Tick() { tickMu.Lock() defer tickMu.Unlock() fmt.Println("Tick!") var err error mgr, err = getACMEManager() if err != nil { fmt.Printf("Error getting acme manager: %v\n", err) return } now := time.Now().UTC() localDomainConfigs := internal.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 = internal.WriteDomainConfig(domainConfig) if err != nil { fmt.Printf("Error saving domain config %s: %v\n", domainStr, err) continue } err = internal.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 = internal.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 := internal.CreateGiteaClient() if giteaClient == nil { fmt.Printf("Error creating gitea client for domain %s: %v\n", domainStr, err) continue } gitWorkspace := &internal.GitWorkspace{ Storage: memory.NewStorage(), FS: memfs.New(), } var repoUrl string if !domainConfig.GetBool("Internal.repo_exists") { repoUrl = internal.CreateGiteaRepo(domainStr, giteaClient) if repoUrl == "" { fmt.Printf("Error creating Gitea repo for domain %s\n", domainStr) continue } domainConfig.Set("Internal.repo_exists", true) err = internal.WriteDomainConfig(domainConfig) if err != nil { fmt.Printf("Error saving domain config %s: %v\n", domainStr, err) continue } err = internal.InitRepo(repoUrl, gitWorkspace) if err != nil { fmt.Printf("Error initializing repo for domain %s: %v\n", domainStr, err) continue } } else { repoUrl = internal.Config().GetString("Git.server") + "/" + internal.Config().GetString("Git.org_name") + "/" + domainStr + domainConfig.GetString("Repo.repo_suffix") + ".git" err = internal.CloneRepo(repoUrl, gitWorkspace, internal.Server) if err != nil { fmt.Printf("Error cloning repo for domain %s: %v\n", domainStr, err) continue } } err = internal.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 = internal.SaveDomainConfigs() if err != nil { fmt.Printf("Error saving domain configs: %v\n", err) } } func Reload() { fmt.Println("Reloading configs...") err := internal.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 Stop() { fmt.Println("Shutting down server") }