Files
certman/app/shared/commands.go
Steven Tracey 18f414e474
All checks were successful
Build (artifact) / build (push) Has been skipped
[CI-SKIP] Fixed module name
2026-03-16 23:03:08 +01:00

192 lines
5.0 KiB
Go

package shared
import (
"fmt"
"log"
"os"
"os/exec"
"os/user"
"strconv"
"strings"
"git.nevets.tech/Steven/certman/common"
"github.com/spf13/cobra"
)
var (
VersionCmd = basicCmd("version", "Show version", versionCmd)
NewKeyCmd = basicCmd("gen-key", "Generates encryption key", newKeyCmd)
DevCmd = basicCmd("dev", "Dev Function", devCmd)
domainCertDir string
NewDomainCmd = &cobra.Command{
Use: "new-domain",
Short: "Create config and directories for new domain",
Args: cobra.ExactArgs(1),
SilenceUsage: true,
SilenceErrors: true,
RunE: func(cmd *cobra.Command, args []string) error {
dirOverridden := cmd.Flags().Changed("dir")
return newDomainCmd(args[0], domainCertDir, dirOverridden)
},
}
modeFlag string
thinInstallFlag bool
InstallCmd = &cobra.Command{
Use: "install",
Short: "Create certman files and directories",
RunE: func(cmd *cobra.Command, args []string) error {
switch modeFlag {
case "server", "client":
return installCmd(thinInstallFlag, modeFlag)
default:
return fmt.Errorf("invalid --mode %q (must be server or client)", modeFlag)
}
},
}
)
func init() {
NewDomainCmd.Flags().StringVar(&domainCertDir, "dir", "/var/local/certman/certificates/", "Alternate directory for certificates")
InstallCmd.Flags().StringVar(&modeFlag, "mode", "client", "CertManager mode [server, client]")
InstallCmd.Flags().BoolVarP(&thinInstallFlag, "thin", "t", false, "Thin install (skip creating dirs)")
}
func devCmd(cmd *cobra.Command, args []string) {
testDomain := "lunamc.org"
err := LoadConfig()
if err != nil {
log.Fatalf("Error loading configuration: %v\n", err)
}
err = LoadDomainConfigs()
if err != nil {
log.Fatalf("Error loading configs: %v\n", err)
}
fmt.Println(testDomain)
}
func versionCmd(cmd *cobra.Command, args []string) {
fmt.Printf("CertManager (certman) - Steven Tracey\nVersion: %s build-%s\n",
common.Version, common.Build,
)
}
func newKeyCmd(cmd *cobra.Command, args []string) {
key, err := common.GenerateKey()
if err != nil {
log.Fatalf("%v", err)
}
fmt.Printf(key)
}
func newDomainCmd(domain, domainDir string, dirOverridden bool) error {
//TODO add config option for "overridden dir"
if !common.IsValidFQDN(domain) {
return fmt.Errorf("invalid FQDN: %q", domain)
}
err := LoadConfig()
if err != nil {
return err
}
fmt.Printf("Creating new domain %s\n", domain)
err = CreateDomainConfig(domain)
if err != nil {
return err
}
CreateDomainCertsDir(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 = common.ChownRecursive("/etc/certman/domains", uid, gid)
if err != nil {
return err
}
err = common.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")
return nil
}
func installCmd(isThin bool, mode string) error {
if !isThin {
if os.Geteuid() != 0 {
return fmt.Errorf("installation must be run as root")
}
MakeDirs()
CreateConfig(mode)
err := LoadConfig()
if err != nil {
return err
}
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 {
if !strings.Contains(err.Error(), "exit status 9") {
return fmt.Errorf("error creating user: %v: output %s", err, output)
}
}
newGroupCmd := exec.Command("groupadd", "-r", "-U", "certman", "certsock")
if output, err := newGroupCmd.CombinedOutput(); err != nil {
if !strings.Contains(err.Error(), "exit status 9") {
return fmt.Errorf("error creating group: %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 = common.ChownRecursive("/etc/certman", uid, gid)
if err != nil {
return fmt.Errorf("error changing uid/gid: %v", err)
}
err = common.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 {
CreateConfig(mode)
}
return nil
}