Moved from ini to toml, fixed installation and new-domain permissions issues
This commit is contained in:
34
certman.service
Normal file
34
certman.service
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=CertMan Certificate Manager Daemon
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
|
||||||
|
User=certman
|
||||||
|
Group=certman
|
||||||
|
|
||||||
|
WorkingDirectory=/var/local/certman
|
||||||
|
|
||||||
|
ExecStart=/usr/local/bin/certman daemon start
|
||||||
|
ExecReload=/usr/local/bin/certman daemon reload
|
||||||
|
ExecStop=/usr/local/bin/certman daemon stop
|
||||||
|
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=2s
|
||||||
|
|
||||||
|
NoNewPrivileges=true
|
||||||
|
PrivateTmp=true
|
||||||
|
ProtectKernelTunables=true
|
||||||
|
ProtectKernelModules=true
|
||||||
|
ProtectControlGroups=true
|
||||||
|
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
|
TimeoutStartSec=30
|
||||||
|
TimeoutStopSec=30
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
18
client.go
18
client.go
@@ -121,6 +121,24 @@ func clientTick() {
|
|||||||
fmt.Printf("Error writing commit hash: %v\n", err)
|
fmt.Printf("Error writing commit hash: %v\n", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
certLinks := domainConfig.GetStringSlice("Certificates.cert_symlinks")
|
||||||
|
for _, certLink := range certLinks {
|
||||||
|
err = 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 = linkFile(filepath.Join(certsDir, domainStr+".crt"), keyLink, domainStr, ".key")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error linking cert %s to %s: %v\n", keyLink, domainStr, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
329
commands.go
329
commands.go
@@ -4,16 +4,24 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-git/go-billy/v5/memfs"
|
||||||
|
"github.com/go-git/go-git/v5/storage/memory"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func devCmd(cmd *cobra.Command, args []string) {
|
func devFunc(cmd *cobra.Command, args []string) {
|
||||||
testDomain := "lunamc.org"
|
testDomain := "lunamc.org"
|
||||||
//config, err = ezconf.LoadConfiguration("/etc/certman/certman.conf")
|
//config, err = ezconf.LoadConfiguration("/etc/certman/certman.conf")
|
||||||
err := LoadConfig("/etc/certman/certman.conf")
|
err := LoadConfig("/etc/certman/certman.conf")
|
||||||
@@ -28,11 +36,11 @@ func devCmd(cmd *cobra.Command, args []string) {
|
|||||||
fmt.Println(testDomain)
|
fmt.Println(testDomain)
|
||||||
}
|
}
|
||||||
|
|
||||||
func versionCmd(cmd *cobra.Command, args []string) {
|
func versionResponse(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("CertManager (certman) - Steven Tracey\nVersion: " + version + " build-" + build)
|
fmt.Println("CertManager (certman) - Steven Tracey\nVersion: " + version + " build-" + build)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newKeyCmd(cmd *cobra.Command, args []string) {
|
func newKey(cmd *cobra.Command, args []string) {
|
||||||
key, err := GenerateKey()
|
key, err := GenerateKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("%v", err)
|
log.Fatalf("%v", err)
|
||||||
@@ -48,20 +56,304 @@ func newDomain(domain, domainDir string, dirOverridden bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
createNewDomainCertsDir(domain, domainDir, dirOverridden)
|
createNewDomainCertsDir(domain, domainDir, dirOverridden)
|
||||||
|
|
||||||
|
certmanUser, err := user.Lookup("certman")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting user certman: %v", err)
|
||||||
|
}
|
||||||
|
uid, err := strconv.Atoi(strings.TrimSpace(certmanUser.Uid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gid, err := strconv.Atoi(strings.TrimSpace(certmanUser.Gid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ChownRecursive("/etc/certman/domains", uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ChownRecursive("/var/local/certman", uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("Successfully created domain entry for " + domain + "\nUpdate config file as needed in /etc/certman/domains/" + domain + ".conf\n")
|
fmt.Println("Successfully created domain entry for " + domain + "\nUpdate config file as needed in /etc/certman/domains/" + domain + ".conf\n")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func install(isThin bool, mode string) error {
|
func install(isThin bool, mode string) error {
|
||||||
if !isThin {
|
if !isThin {
|
||||||
|
if os.Geteuid() != 0 {
|
||||||
|
return fmt.Errorf("installation must be run as root")
|
||||||
|
}
|
||||||
|
|
||||||
makeDirs()
|
makeDirs()
|
||||||
|
createNewConfig(mode)
|
||||||
|
|
||||||
|
f, err := os.OpenFile("/var/run/certman.pid", os.O_RDONLY|os.O_CREATE, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating pid file: %v", err)
|
||||||
|
}
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error closing pid file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newUserCmd := exec.Command("useradd", "-d", "/var/local/certman", "-U", "-r", "-s", "/sbin/nologin", "certman")
|
||||||
|
if output, err := newUserCmd.CombinedOutput(); err != nil {
|
||||||
|
return fmt.Errorf("error creating user: %v: output %s", err, output)
|
||||||
|
}
|
||||||
|
certmanUser, err := user.Lookup("certman")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting user certman: %v", err)
|
||||||
|
}
|
||||||
|
uid, err := strconv.Atoi(strings.TrimSpace(certmanUser.Uid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gid, err := strconv.Atoi(strings.TrimSpace(certmanUser.Gid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ChownRecursive("/etc/certman", uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error changing uid/gid: %v", err)
|
||||||
|
}
|
||||||
|
err = ChownRecursive("/var/local/certman", uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error changing uid/gid: %v", err)
|
||||||
|
}
|
||||||
|
err = os.Chown("/var/run/certman.pid", uid, gid)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error changing uid/gid: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
createNewConfig(mode)
|
||||||
}
|
}
|
||||||
//config, err = ezconf.NewConfiguration(configFile, strings.ReplaceAll(defaultConfig, "{mode}", mode))
|
|
||||||
createNewConfig(mode)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runDaemonCmd() error {
|
func renewCertFunc(domain string, noPush bool) error {
|
||||||
|
err := LoadConfig("/etc/certman/certman.conf")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = LoadDomainConfigs()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch config.GetString("App.mode") {
|
||||||
|
case "server":
|
||||||
|
mgr, err = NewACMEManager()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = renewCerts(domain, noPush)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return reloadDaemon()
|
||||||
|
case "client":
|
||||||
|
return pullCerts(domain)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid operating mode %s", config.GetString("App.mode"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renewCerts(domain string, noPush bool) error {
|
||||||
|
_, err := mgr.RenewForDomain(domain)
|
||||||
|
if err != nil {
|
||||||
|
// if no existing cert, obtain instead
|
||||||
|
_, err = mgr.ObtainForDomain(domain)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error obtaining domain certificates for domain %s: %v", domain, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
domainConfig, exists := domainStore.Get(domain)
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("domain %s does not exist", domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
domainConfig.Set("Internal.last_issued", time.Now().UTC().Unix())
|
||||||
|
err = WriteDomainConfig(domainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error saving domain config %s: %v", domain, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = EncryptFileXChaCha(domainConfig.GetString("Certificates.crypto_key"), filepath.Join(mgr.certsRoot, domain, domain+".crt"), filepath.Join(mgr.certsRoot, domain, domain+".crt.crpt"), nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error encrypting domain cert for domain %s: %v", domain, err)
|
||||||
|
}
|
||||||
|
err = EncryptFileXChaCha(domainConfig.GetString("Certificates.crypto_key"), filepath.Join(mgr.certsRoot, domain, domain+".key"), filepath.Join(mgr.certsRoot, domain, domain+".key.crpt"), nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error encrypting domain key for domain %s: %v", domain, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !noPush {
|
||||||
|
giteaClient := createGiteaClient()
|
||||||
|
if giteaClient == nil {
|
||||||
|
return fmt.Errorf("error creating gitea client for domain %s: %v", domain, err)
|
||||||
|
}
|
||||||
|
gitWorkspace := &GitWorkspace{
|
||||||
|
Storage: memory.NewStorage(),
|
||||||
|
FS: memfs.New(),
|
||||||
|
}
|
||||||
|
|
||||||
|
var repoUrl string
|
||||||
|
if !domainConfig.GetBool("Internal.repo_exists") {
|
||||||
|
repoUrl = createGiteaRepo(domain, giteaClient)
|
||||||
|
if repoUrl == "" {
|
||||||
|
return fmt.Errorf("error creating Gitea repo for domain %s", domain)
|
||||||
|
}
|
||||||
|
domainConfig.Set("Internal.repo_exists", true)
|
||||||
|
err = WriteDomainConfig(domainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error saving domain config %s: %v", domain, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = initRepo(repoUrl, gitWorkspace)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error initializing repo for domain %s: %v", domain, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
repoUrl = config.GetString("Git.server") + "/" + config.GetString("Git.org_name") + "/" + domain + domainConfig.GetString("Repo.repo_suffix") + ".git"
|
||||||
|
err = cloneRepo(repoUrl, gitWorkspace)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error cloning repo for domain %s: %v", domain, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = addAndPushCerts(domain, gitWorkspace)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error pushing certificates for domain %s: %v", domain, err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Successfully pushed certificates for domain %s\n", domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func pullCerts(domain string) error {
|
||||||
|
gitWorkspace := &GitWorkspace{
|
||||||
|
Storage: memory.NewStorage(),
|
||||||
|
FS: memfs.New(),
|
||||||
|
}
|
||||||
|
|
||||||
|
domainConfig, exists := domainStore.Get(domain)
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("domain %s does not exist", domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ex: https://git.example.com/Org/Repo-suffix.git
|
||||||
|
// Clones repo and stores in gitWorkspace, skip if clone fails (doesn't exist?)
|
||||||
|
repoUrl := config.GetString("Git.server") + "/" + config.GetString("Git.org_name") + "/" + domain + domainConfig.GetString("Repo.repo_suffix") + ".git"
|
||||||
|
err := cloneRepo(repoUrl, gitWorkspace)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error cloning domain repo %s: %v\n", domain, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certsDir, err := getDomainCertsDirWConf(domain, domainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error getting certificates dir for domain %s: %v\n", domain, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get files in repo
|
||||||
|
fileInfos, err := gitWorkspace.FS.ReadDir("/")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error reading directory in memFS on domain %s: %v\n", domain, err)
|
||||||
|
}
|
||||||
|
// 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", domain, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fileBytes, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error reading file in memFS on domain %s: %v\n", domain, err)
|
||||||
|
file.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err = file.Close()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error closing file on domain %s: %v\n", domain, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = 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, domain, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
headRef, err := gitWorkspace.Repo.Head()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error getting head reference for domain %s: %v\n", domain, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = 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 {
|
||||||
|
if certLink == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
linkInfo, err := os.Stat(certLink)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
fmt.Printf("Error stating cert link %s: %v\n", certLink, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if linkInfo.IsDir() {
|
||||||
|
certLink = filepath.Join(certLink, domain+".crt")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Link(filepath.Join(certsDir, domain+".crt"), certLink)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error linking cert %s to %s: %v\n", certLink, domain, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyLinks := domainConfig.GetStringSlice("Certificates.key_symlinks")
|
||||||
|
for _, keyLink := range keyLinks {
|
||||||
|
if keyLink == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
linkInfo, err := os.Stat(keyLink)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
fmt.Printf("Error stating key link %s: %v\n", keyLink, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if linkInfo.IsDir() {
|
||||||
|
keyLink = filepath.Join(keyLink, domain+".crt")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Link(filepath.Join(certsDir, domain+".crt"), keyLink)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error linking cert %s to %s: %v\n", keyLink, domain, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runDaemon() error {
|
||||||
err := createOrUpdatePIDFile("/var/run/certman.pid")
|
err := createOrUpdatePIDFile("/var/run/certman.pid")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ErrorPIDInUse) {
|
if errors.Is(err, ErrorPIDInUse) {
|
||||||
@@ -92,6 +384,10 @@ func runDaemonCmd() error {
|
|||||||
signal.Notify(reloadSigChan, syscall.SIGHUP)
|
signal.Notify(reloadSigChan, syscall.SIGHUP)
|
||||||
defer signal.Stop(reloadSigChan)
|
defer signal.Stop(reloadSigChan)
|
||||||
|
|
||||||
|
tickSigChan := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(tickSigChan, syscall.SIGUSR1)
|
||||||
|
defer signal.Stop(tickSigChan)
|
||||||
|
|
||||||
tickRate := config.GetInt("App.tick_rate")
|
tickRate := config.GetInt("App.tick_rate")
|
||||||
ticker := time.NewTicker(time.Duration(tickRate) * time.Hour)
|
ticker := time.NewTicker(time.Duration(tickRate) * time.Hour)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
@@ -112,6 +408,8 @@ func runDaemonCmd() error {
|
|||||||
reloadServer()
|
reloadServer()
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
serverTick()
|
serverTick()
|
||||||
|
case <-tickSigChan:
|
||||||
|
serverTick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -151,7 +449,7 @@ func stop() {
|
|||||||
clearPIDFile()
|
clearPIDFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopDaemonCmd() error {
|
func stopDaemon() error {
|
||||||
proc, err := getDaemonProcess()
|
proc, err := getDaemonProcess()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error getting daemon process: %v", err)
|
return fmt.Errorf("error getting daemon process: %v", err)
|
||||||
@@ -164,7 +462,7 @@ func stopDaemonCmd() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func reloadDaemonCmd() error {
|
func reloadDaemon() error {
|
||||||
proc, err := getDaemonProcess()
|
proc, err := getDaemonProcess()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error getting daemon process: %v", err)
|
return fmt.Errorf("error getting daemon process: %v", err)
|
||||||
@@ -177,7 +475,20 @@ func reloadDaemonCmd() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func statusDaemonCmd() error {
|
func tickDaemon() error {
|
||||||
|
proc, err := getDaemonProcess()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error getting daemon process: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = proc.Signal(syscall.SIGUSR1)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error sending SIGUSR1 to daemon PID: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func statusDaemon() error {
|
||||||
fmt.Println("Not implemented :/")
|
fmt.Println("Not implemented :/")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
88
config.go
88
config.go
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
@@ -9,6 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -76,7 +78,7 @@ var (
|
|||||||
func LoadConfig(path string) error {
|
func LoadConfig(path string) error {
|
||||||
config = viper.New()
|
config = viper.New()
|
||||||
config.SetConfigFile(path)
|
config.SetConfigFile(path)
|
||||||
config.SetConfigType("ini")
|
config.SetConfigType("toml")
|
||||||
return config.ReadInConfig()
|
return config.ReadInConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +100,7 @@ func LoadDomainConfigs() error {
|
|||||||
path := filepath.Join(dir, entry.Name())
|
path := filepath.Join(dir, entry.Name())
|
||||||
v := viper.New()
|
v := viper.New()
|
||||||
v.SetConfigFile(path)
|
v.SetConfigFile(path)
|
||||||
v.SetConfigType("ini")
|
v.SetConfigType("toml")
|
||||||
|
|
||||||
if err := v.ReadInConfig(); err != nil {
|
if err := v.ReadInConfig(); err != nil {
|
||||||
return fmt.Errorf("loading %s: %w", path, err)
|
return fmt.Errorf("loading %s: %w", path, err)
|
||||||
@@ -124,13 +126,35 @@ func LoadDomainConfigs() error {
|
|||||||
// Saving
|
// Saving
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
func WriteConfig(filePath string, config *viper.Viper) error {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := config.WriteConfigTo(&buf); err != nil {
|
||||||
|
return fmt.Errorf("marshal config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.WriteFile(filePath, buf.Bytes(), 0640); err != nil {
|
||||||
|
return fmt.Errorf("write config file: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteMainConfig() error {
|
||||||
|
return WriteConfig("/etc/certman/certman.conf", config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteDomainConfig(config *viper.Viper) error {
|
||||||
|
return WriteConfig(config.GetString("Domain.domain_name"), config)
|
||||||
|
}
|
||||||
|
|
||||||
// SaveDomainConfigs writes every loaded domain config back to disk.
|
// SaveDomainConfigs writes every loaded domain config back to disk.
|
||||||
func SaveDomainConfigs() {
|
func SaveDomainConfigs() error {
|
||||||
for domain, v := range domainStore.Snapshot() {
|
for domain, v := range domainStore.Snapshot() {
|
||||||
if err := v.WriteConfig(); err != nil {
|
err := WriteConfig("/etc/certman/domains/"+domain+".conf", v)
|
||||||
fmt.Printf("Error saving domain config %s: %v\n", domain, err)
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -217,8 +241,11 @@ func makeDirs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createNewConfig(mode string) {
|
func createNewConfig(mode string) {
|
||||||
content := strings.NewReplacer("{mode}", mode).Replace(defaultConfig)
|
content := strings.NewReplacer(
|
||||||
createFile("/etc/certman/certman.conf", 640, []byte(content))
|
"{mode}", mode,
|
||||||
|
"{uuid}", uuid.New().String(),
|
||||||
|
).Replace(defaultConfig)
|
||||||
|
createFile("/etc/certman/certman.conf", 0640, []byte(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNewDomainConfig(domain string) error {
|
func createNewDomainConfig(domain string) error {
|
||||||
@@ -259,52 +286,49 @@ func createNewDomainCertsDir(domain string, dir string, dirOverride bool) {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
const defaultConfig = `[App]
|
const defaultConfig = `[App]
|
||||||
mode = {mode}
|
mode = "{mode}"
|
||||||
tick_rate = 2
|
tick_rate = 2
|
||||||
|
uuid = "{uuid}"
|
||||||
|
|
||||||
[Git]
|
[Git]
|
||||||
host = gitea
|
host = "gitea"
|
||||||
server = https://gitea.instance.com
|
server = "https://gitea.instance.com"
|
||||||
username = user
|
username = "user"
|
||||||
api_token = xxxxxxxxxxxxxxxxxxxxxxxxx
|
api_token = "xxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
org_name = org
|
org_name = "org"
|
||||||
|
|
||||||
[Certificates]
|
[Certificates]
|
||||||
email = user@example.com
|
email = "user@example.com"
|
||||||
data_root = /var/local/certman
|
data_root = "/var/local/certman"
|
||||||
ca_dir_url = https://acme-v02.api.letsencrypt.org/directory
|
ca_dir_url = "https://acme-v02.api.letsencrypt.org/directory"
|
||||||
|
|
||||||
[Cloudflare]
|
[Cloudflare]
|
||||||
cf_email = email@example.com
|
cf_email = "email@example.com"
|
||||||
cf_api_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
cf_api_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
`
|
`
|
||||||
|
|
||||||
const defaultDomainConfig = `[Domain]
|
const defaultDomainConfig = `[Domain]
|
||||||
domain_name = {domain}
|
domain_name = "{domain}"
|
||||||
enabled = true
|
enabled = true
|
||||||
dns_server = default
|
dns_server = "default"
|
||||||
|
|
||||||
|
|
||||||
[Certificates]
|
[Certificates]
|
||||||
data_root =
|
data_root = ""
|
||||||
expiry = 90
|
expiry = 90
|
||||||
request_method = dns-01
|
request_method = "dns-01"
|
||||||
renew_period = 30
|
renew_period = 30
|
||||||
|
subdomains = []
|
||||||
subdomains =
|
cert_symlinks = []
|
||||||
cert_symlink =
|
key_symlinks = []
|
||||||
key_symlink =
|
crypto_key = "{key}"
|
||||||
crypto_key = {key}
|
|
||||||
|
|
||||||
|
|
||||||
[Repo]
|
[Repo]
|
||||||
repo_suffix = -certificates
|
repo_suffix = "-certificates"
|
||||||
|
|
||||||
|
|
||||||
[Internal]
|
[Internal]
|
||||||
last_issued = 0
|
last_issued = 0
|
||||||
repo_exists = false
|
repo_exists = false
|
||||||
status = clean
|
status = "clean"
|
||||||
`
|
`
|
||||||
|
|
||||||
const readme = ``
|
const readme = ``
|
||||||
|
|||||||
62
git.go
62
git.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -98,18 +99,6 @@ func createGiteaRepo(domain string, giteaClient *gitea.Client) string {
|
|||||||
fmt.Printf("Domain %s config does not exist\n", domain)
|
fmt.Printf("Domain %s config does not exist\n", domain)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
//options := gitea.CreateRepoFromTemplateOption{
|
|
||||||
// Avatar: true,
|
|
||||||
// Description: "Certificates storage for " + domain,
|
|
||||||
// GitContent: true,
|
|
||||||
// GitHooks: true,
|
|
||||||
// Labels: true,
|
|
||||||
// Name: domain + domainConfig.GetAsString("Repo.repo_suffix"),
|
|
||||||
// Owner: config.GetAsString("Git.org_name"),
|
|
||||||
// Private: true,
|
|
||||||
// Topics: true,
|
|
||||||
// Webhooks: true,
|
|
||||||
//}
|
|
||||||
options := gitea.CreateRepoOption{
|
options := gitea.CreateRepoOption{
|
||||||
Name: domain + domainConfig.GetString("Repo.repo_suffix"),
|
Name: domain + domainConfig.GetString("Repo.repo_suffix"),
|
||||||
Description: "Certificate storage for " + domain,
|
Description: "Certificate storage for " + domain,
|
||||||
@@ -174,6 +163,22 @@ func cloneRepo(url string, ws *GitWorkspace) error {
|
|||||||
fmt.Printf("Error getting worktree from cloned repo: %v\n", err)
|
fmt.Printf("Error getting worktree from cloned repo: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
serverIdFile, err := ws.FS.OpenFile("/SERVER_ID", os.O_RDWR, 0640)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
fmt.Printf("Server ID file not found for %s, adopting domain\n", url)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
serverIdBytes, err := io.ReadAll(serverIdFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
serverId := strings.TrimSpace(string(serverIdBytes))
|
||||||
|
if serverId != config.GetString("App.uuid") {
|
||||||
|
return fmt.Errorf("domain is already managed by server with uuid %s", serverId)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +210,7 @@ func addAndPushCerts(domain string, ws *GitWorkspace) error {
|
|||||||
fmt.Printf("Error copying file to memfs: %v\n", err)
|
fmt.Printf("Error copying file to memfs: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
certFile, err := os.ReadFile(filepath.Join(certsDir, file.Name()))
|
certFile, err := os.ReadFile(filepath.Join(certsDir, entry.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error reading file to memfs: %v\n", err)
|
fmt.Printf("Error reading file to memfs: %v\n", err)
|
||||||
file.Close()
|
file.Close()
|
||||||
@@ -228,6 +233,29 @@ func addAndPushCerts(domain string, ws *GitWorkspace) error {
|
|||||||
fmt.Printf("Error closing file: %v\n", err)
|
fmt.Printf("Error closing file: %v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file, err := ws.FS.Create("/SERVER_ID")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error creating file in memfs: %v\n", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = file.Write([]byte(config.GetString("App.uuid")))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error writing to memfs: %v\n", err)
|
||||||
|
file.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = ws.WorkTree.Add(file.Name())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error adding file %v: %v\n", file.Name(), err)
|
||||||
|
file.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = file.Close()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error closing file: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status, err := ws.WorkTree.Status()
|
status, err := ws.WorkTree.Status()
|
||||||
@@ -246,7 +274,7 @@ func addAndPushCerts(domain string, ws *GitWorkspace) error {
|
|||||||
Email: config.GetString("Certificates.email"),
|
Email: config.GetString("Certificates.email"),
|
||||||
When: time.Now(),
|
When: time.Now(),
|
||||||
}
|
}
|
||||||
commitHash, err := ws.WorkTree.Commit("Update "+domain+" @ "+time.Now().Format("Mon Jan _2 2006 15:04:05 MST"), &git.CommitOptions{Author: signature, Committer: signature})
|
_, err = ws.WorkTree.Commit("Update "+domain+" @ "+time.Now().Format("Mon Jan _2 2006 15:04:05 MST"), &git.CommitOptions{Author: signature, Committer: signature})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error committing certs: %v\n", err)
|
fmt.Printf("Error committing certs: %v\n", err)
|
||||||
return err
|
return err
|
||||||
@@ -270,12 +298,6 @@ func addAndPushCerts(domain string, ws *GitWorkspace) error {
|
|||||||
|
|
||||||
fmt.Println("Successfully uploaded to " + config.GetString("Git.server") + "/" + config.GetString("Git.org_name") + "/" + domain + domainConfig.GetString("Repo.repo_suffix") + ".git")
|
fmt.Println("Successfully uploaded to " + config.GetString("Git.server") + "/" + config.GetString("Git.org_name") + "/" + domain + domainConfig.GetString("Repo.repo_suffix") + ".git")
|
||||||
|
|
||||||
err = writeCommitHash(commitHash.String(), domainConfig)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error writing commit hash: %v\n", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
85
go.mod
85
go.mod
@@ -1,63 +1,58 @@
|
|||||||
module main
|
module main
|
||||||
|
|
||||||
go 1.24.0
|
go 1.25.0
|
||||||
|
|
||||||
toolchain go1.24.7
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.gitea.io/sdk/gitea v0.15.1
|
code.gitea.io/sdk/gitea v0.23.2
|
||||||
github.com/go-acme/lego/v4 v4.26.0
|
github.com/go-acme/lego/v4 v4.32.0
|
||||||
github.com/go-git/go-billy/v5 v5.4.1
|
github.com/go-git/go-billy/v5 v5.8.0
|
||||||
github.com/go-git/go-git/v5 v5.7.0
|
github.com/go-git/go-git/v5 v5.17.0
|
||||||
github.com/google/go-github/v55 v55.0.0
|
github.com/google/go-github/v55 v55.0.0
|
||||||
|
github.com/google/uuid v1.6.0
|
||||||
github.com/spf13/cobra v1.10.2
|
github.com/spf13/cobra v1.10.2
|
||||||
github.com/spf13/viper v1.18.2
|
github.com/spf13/viper v1.21.0
|
||||||
golang.org/x/crypto v0.42.0
|
golang.org/x/crypto v0.48.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.5.2 // indirect
|
dario.cat/mergo v1.0.2 // indirect
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 // indirect
|
github.com/42wim/httpsig v1.2.3 // indirect
|
||||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/ProtonMail/go-crypto v1.3.0 // indirect
|
||||||
github.com/cloudflare/circl v1.3.3 // indirect
|
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||||
|
github.com/cloudflare/circl v1.6.3 // indirect
|
||||||
|
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||||
|
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||||
|
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.1.2 // indirect
|
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||||
github.com/hashicorp/go-version v1.7.0 // indirect
|
github.com/google/go-querystring v1.2.0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/go-version v1.8.0 // indirect
|
||||||
github.com/imdario/mergo v0.3.15 // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
github.com/kevinburke/ssh_config v1.6.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
github.com/miekg/dns v1.1.68 // indirect
|
github.com/miekg/dns v1.1.72 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
github.com/pjbgf/sha1cd v0.5.0 // indirect
|
||||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
github.com/sergi/go-diff v1.4.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/skeema/knownhosts v1.3.2 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/spf13/afero v1.15.0 // indirect
|
||||||
github.com/sergi/go-diff v1.3.1 // indirect
|
github.com/spf13/cast v1.10.0 // indirect
|
||||||
github.com/skeema/knownhosts v1.1.1 // indirect
|
github.com/spf13/pflag v1.0.10 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
|
||||||
github.com/spf13/afero v1.11.0 // indirect
|
|
||||||
github.com/spf13/cast v1.7.0 // indirect
|
|
||||||
github.com/spf13/pflag v1.0.9 // indirect
|
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
|
golang.org/x/mod v0.33.0 // indirect
|
||||||
golang.org/x/mod v0.27.0 // indirect
|
golang.org/x/net v0.51.0 // indirect
|
||||||
golang.org/x/net v0.44.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/sync v0.17.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/sys v0.36.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
golang.org/x/text v0.29.0 // indirect
|
golang.org/x/tools v0.42.0 // indirect
|
||||||
golang.org/x/tools v0.36.0 // indirect
|
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
230
go.sum
230
go.sum
@@ -1,171 +1,147 @@
|
|||||||
code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
|
code.gitea.io/sdk/gitea v0.23.2 h1:iJB1FDmLegwfwjX8gotBDHdPSbk/ZR8V9VmEJaVsJYg=
|
||||||
code.gitea.io/sdk/gitea v0.15.1 h1:WJreC7YYuxbn0UDaPuWIe/mtiNKTvLN8MLkaw71yx/M=
|
code.gitea.io/sdk/gitea v0.23.2/go.mod h1:yyF5+GhljqvA30sRDreoyHILruNiy4ASufugzYg0VHM=
|
||||||
code.gitea.io/sdk/gitea v0.15.1/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
|
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||||
|
github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs=
|
||||||
|
github.com/42wim/httpsig v1.2.3/go.mod h1:nZq9OlYKDrUBhptd77IHx4/sZZD+IxTBADvAPI9G/EM=
|
||||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek=
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
|
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
|
||||||
github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
|
||||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
|
||||||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
|
||||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
|
||||||
|
github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0=
|
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||||
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||||
|
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
|
||||||
|
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
|
||||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||||
github.com/go-acme/lego/v4 v4.26.0 h1:521aEQxNstXvPQcFDDPrJiFfixcCQuvAvm35R4GbyYA=
|
github.com/go-acme/lego/v4 v4.32.0 h1:z7Ss7aa1noabhKj+DBzhNCO2SM96xhE3b0ucVW3x8Tc=
|
||||||
github.com/go-acme/lego/v4 v4.26.0/go.mod h1:BQVAWgcyzW4IT9eIKHY/RxYlVhoyKyOMXOkq7jK1eEQ=
|
github.com/go-acme/lego/v4 v4.32.0/go.mod h1:lI2fZNdgeM/ymf9xQ9YKbgZm6MeDuf91UrohMQE4DhI=
|
||||||
|
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||||
|
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||||
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
|
github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0=
|
||||||
github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||||
github.com/go-git/go-git/v5 v5.7.0 h1:t9AudWVLmqzlo+4bqdf7GY+46SUuRsx59SboFxkq2aE=
|
github.com/go-git/go-git/v5 v5.17.0 h1:AbyI4xf+7DsjINHMu35quAh4wJygKBKBuXVjV/pxesM=
|
||||||
github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhcZd8Fodw8=
|
github.com/go-git/go-git/v5 v5.17.0/go.mod h1:f82C4YiLx+Lhi8eHxltLeGC5uBTXSFa6PC5WW9o4SjI=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.2 h1:TK/7NqRQZfgAh+Td8AlsrvtPoUyiHh0LqVvokh+1vHI=
|
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
|
||||||
github.com/go-jose/go-jose/v4 v4.1.2/go.mod h1:22cg9HWM1pOlnRiY+9cQYJ9XHmya1bYW8OeDM6Ku6Oo=
|
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||||
|
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/go-github/v55 v55.0.0 h1:4pp/1tNMB9X/LuAhs5i0KQAE40NmiR/y6prLNb9x9cg=
|
github.com/google/go-github/v55 v55.0.0 h1:4pp/1tNMB9X/LuAhs5i0KQAE40NmiR/y6prLNb9x9cg=
|
||||||
github.com/google/go-github/v55 v55.0.0/go.mod h1:JLahOTA1DnXzhxEymmFF5PP2tSS9JVNj68mSZNDwskA=
|
github.com/google/go-github/v55 v55.0.0/go.mod h1:JLahOTA1DnXzhxEymmFF5PP2tSS9JVNj68mSZNDwskA=
|
||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.2.0 h1:yhqkPbu2/OH+V9BfpCVPZkNmUXhb2gBxJArfhIxNtP0=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.2.0/go.mod h1:8IFJqpSRITyJ8QhQ13bmbeMBDfmeEJZD5A0egEOmkqU=
|
||||||
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
|
||||||
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
|
|
||||||
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
github.com/kevinburke/ssh_config v1.6.0 h1:J1FBfmuVosPHf5GRdltRLhPJtJpTlMdKTBjRgTaQBFY=
|
||||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
github.com/kevinburke/ssh_config v1.6.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
|
||||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
|
||||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||||
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||||
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
|
||||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
|
||||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
|
||||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
|
||||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/skeema/knownhosts v1.1.1 h1:MTk78x9FPgDFVFkDLTrsnnfCJl7g1C/nnKvePgrIngE=
|
github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg=
|
||||||
github.com/skeema/knownhosts v1.1.1/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo=
|
github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow=
|
||||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
|
||||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
|
||||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||||
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||||
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
|
|
||||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||||
|
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
|
||||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
|
||||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU=
|
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU=
|
||||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
|
||||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
|
||||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -173,49 +149,27 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
|
||||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
|
||||||
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
|
||||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
|
||||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|
||||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
|
||||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
|
||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
|
||||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
97
main.go
97
main.go
@@ -4,13 +4,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"regexp"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "1.0.0"
|
var version = "1.0.0"
|
||||||
var build = "2"
|
var build = "1"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
configFile string
|
configFile string
|
||||||
@@ -19,6 +20,8 @@ var (
|
|||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var fqdnRegex = regexp.MustCompile(`^(?i:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$`)
|
||||||
|
|
||||||
//TODO create logic for gh vs gt repos
|
//TODO create logic for gh vs gt repos
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -33,9 +36,9 @@ func main() {
|
|||||||
|
|
||||||
rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "/etc/certman/certman.conf", "Configuration file")
|
rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "/etc/certman/certman.conf", "Configuration file")
|
||||||
|
|
||||||
rootCmd.AddCommand(basicCmd("version", "Show version", versionCmd))
|
rootCmd.AddCommand(basicCmd("version", "Show version", versionResponse))
|
||||||
rootCmd.AddCommand(basicCmd("gen-key", "Generates encryption key", newKeyCmd))
|
rootCmd.AddCommand(basicCmd("gen-key", "Generates encryption key", newKey))
|
||||||
rootCmd.AddCommand(basicCmd("dev", "Dev Function", devCmd))
|
rootCmd.AddCommand(basicCmd("dev", "Dev Function", devFunc))
|
||||||
|
|
||||||
var domainCertDir string
|
var domainCertDir string
|
||||||
newDomainCmd := &cobra.Command{
|
newDomainCmd := &cobra.Command{
|
||||||
@@ -72,6 +75,28 @@ func main() {
|
|||||||
installCmd.Flags().BoolVarP(&thinInstallFlag, "thin", "t", false, "Thin install (skip creating dirs)")
|
installCmd.Flags().BoolVarP(&thinInstallFlag, "thin", "t", false, "Thin install (skip creating dirs)")
|
||||||
rootCmd.AddCommand(installCmd)
|
rootCmd.AddCommand(installCmd)
|
||||||
|
|
||||||
|
certCmd := &cobra.Command{
|
||||||
|
Use: "cert",
|
||||||
|
Short: "Certificate management",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return cmd.Help()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var noPush bool
|
||||||
|
renewCertCmd := &cobra.Command{
|
||||||
|
Use: "renew",
|
||||||
|
Short: "Renews a domains certificate",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return renewCertFunc(args[0], noPush)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
renewCertCmd.Flags().BoolVar(&noPush, "no-push", false, "Don't push certs to repo, renew locally only [server mode only]")
|
||||||
|
certCmd.AddCommand(renewCertCmd)
|
||||||
|
|
||||||
|
rootCmd.AddCommand(certCmd)
|
||||||
|
|
||||||
daemonCmd := &cobra.Command{
|
daemonCmd := &cobra.Command{
|
||||||
Use: "daemon",
|
Use: "daemon",
|
||||||
Short: "Daemon management",
|
Short: "Daemon management",
|
||||||
@@ -85,7 +110,7 @@ func main() {
|
|||||||
Short: "Start the daemon",
|
Short: "Start the daemon",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return runDaemonCmd()
|
return runDaemon()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -94,7 +119,7 @@ func main() {
|
|||||||
Short: "Stop the daemon",
|
Short: "Stop the daemon",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return stopDaemonCmd()
|
return stopDaemon()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -103,7 +128,16 @@ func main() {
|
|||||||
Short: "Reload daemon configs",
|
Short: "Reload daemon configs",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return reloadDaemonCmd()
|
return reloadDaemon()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
daemonCmd.AddCommand(&cobra.Command{
|
||||||
|
Use: "tick",
|
||||||
|
Short: "Manually triggers daemon tick",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return tickDaemon()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -112,7 +146,7 @@ func main() {
|
|||||||
Short: "Show daemon status",
|
Short: "Show daemon status",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return statusDaemonCmd()
|
return statusDaemon()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -132,47 +166,6 @@ func basicCmd(use, short string, commandFunc func(cmd *cobra.Command, args []str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// case "gen":
|
func IsValidFQDN(domain string) bool {
|
||||||
// {
|
return len(domain) <= 253 && fqdnRegex.MatchString(domain)
|
||||||
// url := createGiteaRepo(domain)
|
}
|
||||||
// if url == "" {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// gitWorkspace.Repo, gitWorkspace.WorkTree = cloneRepo(url, gitWorkspace)
|
|
||||||
// if gitWorkspace.Repo == nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// cmd = exec.Command("lego", legoNewSiteArgs...)
|
|
||||||
// }
|
|
||||||
// case "renew":
|
|
||||||
// {
|
|
||||||
// gitWorkspace.Repo, gitWorkspace.WorkTree = cloneRepo(config.GetAsString("Git.server")+"/"+config.GetAsString("Git.org_name")+"/"+domain+"-certificates.git", gitWorkspace)
|
|
||||||
// if gitWorkspace.Repo == nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// cmd = exec.Command("lego", legoRenewSiteArgs...)
|
|
||||||
// }
|
|
||||||
// case "gen-cert-only":
|
|
||||||
// {
|
|
||||||
// cmd = exec.Command("lego", legoNewSiteArgs...)
|
|
||||||
// }
|
|
||||||
// case "renew-cert-only":
|
|
||||||
// {
|
|
||||||
// cmd = exec.Command("lego", legoRenewSiteArgs...)
|
|
||||||
// }
|
|
||||||
// case "git":
|
|
||||||
// {
|
|
||||||
// url := createGiteaRepo(domain)
|
|
||||||
// if url == "" {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// gitWorkspace.Repo, gitWorkspace.WorkTree = cloneRepo(url, gitWorkspace)
|
|
||||||
// if gitWorkspace.Repo == nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// err := addAndPushCerts(domain, gitWorkspace)
|
|
||||||
// if err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// os.Exit(0)
|
|
||||||
// }
|
|
||||||
|
|||||||
10
server.go
10
server.go
@@ -63,6 +63,7 @@ func serverTick() {
|
|||||||
lastIssued := time.Unix(domainConfig.GetInt64("Internal.last_issued"), 0).UTC()
|
lastIssued := time.Unix(domainConfig.GetInt64("Internal.last_issued"), 0).UTC()
|
||||||
renewalDue := lastIssued.AddDate(0, 0, renewPeriod)
|
renewalDue := lastIssued.AddDate(0, 0, renewPeriod)
|
||||||
if now.After(renewalDue) {
|
if now.After(renewalDue) {
|
||||||
|
//TODO extra check if certificate expiry (create cache?)
|
||||||
_, err = mgr.RenewForDomain(domainStr)
|
_, err = mgr.RenewForDomain(domainStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// if no existing cert, obtain instead
|
// if no existing cert, obtain instead
|
||||||
@@ -74,7 +75,7 @@ func serverTick() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
domainConfig.Set("Internal.last_issued", time.Now().UTC().Unix())
|
domainConfig.Set("Internal.last_issued", time.Now().UTC().Unix())
|
||||||
err = domainConfig.WriteConfig()
|
err = WriteDomainConfig(domainConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error saving domain config %s: %v\n", domainStr, err)
|
fmt.Printf("Error saving domain config %s: %v\n", domainStr, err)
|
||||||
continue
|
continue
|
||||||
@@ -109,7 +110,7 @@ func serverTick() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
domainConfig.Set("Internal.repo_exists", true)
|
domainConfig.Set("Internal.repo_exists", true)
|
||||||
err = domainConfig.WriteConfig()
|
err = WriteDomainConfig(domainConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error saving domain config %s: %v\n", domainStr, err)
|
fmt.Printf("Error saving domain config %s: %v\n", domainStr, err)
|
||||||
continue
|
continue
|
||||||
@@ -137,7 +138,10 @@ func serverTick() {
|
|||||||
fmt.Printf("Successfully pushed certificates for domain %s\n", domainStr)
|
fmt.Printf("Successfully pushed certificates for domain %s\n", domainStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SaveDomainConfigs()
|
err = SaveDomainConfigs()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error saving domain configs: %v\n", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func reloadServer() {
|
func reloadServer() {
|
||||||
|
|||||||
35
util.go
35
util.go
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -15,9 +16,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrorPIDInUse = errors.New("daemon is already running")
|
ErrorPIDInUse = errors.New("daemon is already running")
|
||||||
ErrLockFailed = errors.New("failed to acquire a lock on the PID file")
|
ErrLockFailed = errors.New("failed to acquire a lock on the PID file")
|
||||||
ErrRepoNotInit = errors.New("repo not initialized")
|
ErrBlankCert = errors.New("cert is blank")
|
||||||
)
|
)
|
||||||
|
|
||||||
type Domain struct {
|
type Domain struct {
|
||||||
@@ -208,10 +209,22 @@ func createFile(fileName string, filePermission os.FileMode, data []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkFile(source, target string) error {
|
func linkFile(source, target, domain, extension string) error {
|
||||||
err := os.Symlink(source, target)
|
if target == "" {
|
||||||
|
return ErrBlankCert
|
||||||
|
}
|
||||||
|
linkInfo, err := os.Stat(target)
|
||||||
|
if err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if linkInfo.IsDir() {
|
||||||
|
target = filepath.Join(target, domain+extension)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Symlink(source, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error creating symlink:", err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -269,3 +282,13 @@ func getDomainCertsDirWOnlyConf(domainConfig *viper.Viper) (string, error) {
|
|||||||
domain := domainConfig.GetString("Domain.domain_name")
|
domain := domainConfig.GetString("Domain.domain_name")
|
||||||
return getDomainCertsDirWConf(domain, domainConfig)
|
return getDomainCertsDirWConf(domain, domainConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ChownRecursive(path string, uid, gid int) error {
|
||||||
|
return filepath.WalkDir(path, func(name string, d fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err // Stop if we encounter a permission error on a specific file
|
||||||
|
}
|
||||||
|
// Apply ownership change to the current item
|
||||||
|
return os.Chown(name, uid, gid)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user