package client import ( "fmt" "io" "log" "path/filepath" "strings" "git.nevets.tech/Keys/CertManager/internal" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5/storage/memory" ) func Init() { err := internal.LoadDomainConfigs() if err != nil { log.Fatalf("Error loading domain configs: %v", err) } Tick() } func Tick() { fmt.Println("Tick!") // Get local copy of configs config := internal.Config() localDomainConfigs := internal.DomainStore().Snapshot() // Loop over all domain configs (domains) for domainStr, domainConfig := range localDomainConfigs { // Skip non-enabled domains if !domainConfig.GetBool("Domain.enabled") { continue } // Skip domains with up-to-date commit hashes // If the repo doesn't exist, we can't check for a remote commit, so stop the rest of the check repoExists := domainConfig.GetBool("Internal.repo_exists") if repoExists { localHash, err := internal.LocalCommitHash(domainStr) if err != nil { fmt.Printf("No local commit hash found for domain %s\n", domainStr) } gitSource, err := internal.StrToGitSource(internal.Config().GetString("Git.host")) if err != nil { fmt.Printf("Error getting git source for domain %s: %v\n", domainStr, err) continue } remoteHash, err := internal.RemoteCommitHash(domainStr, gitSource) if err != nil { fmt.Printf("Error getting remote commit hash for domain %s: %v\n", domainStr, err) } // If both hashes are blank (errored), break // If localHash equals remoteHash (local is up-to-date), skip if !(localHash == "" && remoteHash == "") && localHash == remoteHash { fmt.Printf("Domain %s is up to date. Skipping...\n", domainStr) continue } } gitWorkspace := &internal.GitWorkspace{ Storage: memory.NewStorage(), FS: memfs.New(), } // Ex: https://git.example.com/Org/Repo-suffix.git // Clones repo and stores in gitWorkspace, skip if clone fails (doesn't exist?) repoUrl := internal.Config().GetString("Git.server") + "/" + config.GetString("Git.org_name") + "/" + domainStr + domainConfig.GetString("Repo.repo_suffix") + ".git" err := internal.CloneRepo(repoUrl, gitWorkspace, internal.Client) if err != nil { fmt.Printf("Error cloning domain repo %s: %v\n", domainStr, err) continue } certsDir, err := internal.DomainCertsDirWConf(domainStr, domainConfig) if err != nil { fmt.Printf("Error getting certificates dir for domain %s: %v\n", domainStr, err) continue } // Get files in repo fileInfos, err := gitWorkspace.FS.ReadDir("/") if err != nil { fmt.Printf("Error reading directory in memFS on domain %s: %v\n", domainStr, err) continue } // Iterate over files, filtering by .crpt (encrypted) files in case other files were accidentally added for _, fileInfo := range fileInfos { if strings.HasSuffix(fileInfo.Name(), ".crpt") { filename, _ := strings.CutSuffix(fileInfo.Name(), ".crpt") file, err := gitWorkspace.FS.Open(fileInfo.Name()) if err != nil { fmt.Printf("Error opening file in memFS on domain %s: %v\n", domainStr, err) continue } fileBytes, err := io.ReadAll(file) if err != nil { fmt.Printf("Error reading file in memFS on domain %s: %v\n", domainStr, err) file.Close() continue } err = file.Close() if err != nil { fmt.Printf("Error closing file on domain %s: %v\n", domainStr, err) continue } err = internal.DecryptFileFromBytes(domainConfig.GetString("Certificates.crypto_key"), fileBytes, filepath.Join(certsDir, filename), nil) if err != nil { fmt.Printf("Error decrypting file %s in domain %s: %v\n", filename, domainStr, err) continue } headRef, err := gitWorkspace.Repo.Head() if err != nil { fmt.Printf("Error getting head reference for domain %s: %v\n", domainStr, err) continue } err = internal.WriteCommitHash(headRef.Hash().String(), domainConfig) if err != nil { fmt.Printf("Error writing commit hash: %v\n", err) continue } certLinks := domainConfig.GetStringSlice("Certificates.cert_symlinks") for _, certLink := range certLinks { err = internal.LinkFile(filepath.Join(certsDir, domainStr+".crt"), certLink, domainStr, ".crt") if err != nil { fmt.Printf("Error linking cert %s to %s: %v\n", certLink, domainStr, err) continue } } keyLinks := domainConfig.GetStringSlice("Certificates.key_symlinks") for _, keyLink := range keyLinks { err = internal.LinkFile(filepath.Join(certsDir, domainStr+".key"), keyLink, domainStr, ".key") if err != nil { fmt.Printf("Error linking cert %s to %s: %v\n", keyLink, domainStr, err) continue } } } } } } func Reload() { fmt.Println("Reloading configs...") err := internal.LoadDomainConfigs() if err != nil { fmt.Printf("Error loading domain configs: %v\n", err) return } } func Stop() { fmt.Println("Shutting down client") }