162 lines
4.9 KiB
Go
162 lines
4.9 KiB
Go
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")
|
|
}
|