All checks were successful
Build (artifact) / build (push) Successful in 27s
231 lines
5.9 KiB
Go
231 lines
5.9 KiB
Go
package app
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"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", GenKeyCmd)
|
|
UpdateCmd = basicCmd("update", "Updates if new version is found", updateCmd)
|
|
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 GenKeyCmd(cmd *cobra.Command, args []string) {
|
|
key, err := common.GenerateKey()
|
|
if err != nil {
|
|
log.Fatalf("%v", err)
|
|
}
|
|
fmt.Printf(key)
|
|
}
|
|
|
|
func updateCmd(cmd *cobra.Command, args []string) {
|
|
if os.Geteuid() != 0 {
|
|
log.Fatal(fmt.Errorf("installation must be run as root"))
|
|
}
|
|
|
|
err := LoadConfig()
|
|
if err != nil {
|
|
log.Fatalf("%v", err)
|
|
}
|
|
resp, err := http.Get(SourceCertmanRepo + "/latest")
|
|
if err != nil {
|
|
log.Fatalf("%v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
|
|
var release GiteaRelease
|
|
err = json.Unmarshal(body, &release)
|
|
if err != nil {
|
|
log.Fatalf("%v", err)
|
|
}
|
|
|
|
for _, asset := range release.Assets {
|
|
if strings.Contains(asset.Name, Config().App.Mode) {
|
|
if !strings.Contains(asset.Name, common.Version) {
|
|
fmt.Printf("Found a newer version: %s\n", asset.Name)
|
|
err = downloadFile("/usr/local/bin/certman", SourceCertmanRepo+"/"+strconv.Itoa(release.Id)+"/assets/"+strconv.Itoa(asset.Id))
|
|
if err != nil {
|
|
log.Fatalf("%v", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
//TODO chmod after chown
|
|
uid, gid, err := GetUserIds("certman")
|
|
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)
|
|
}
|
|
|
|
//TODO move executable to /usr/bin
|
|
//execPath, err := os.Executable()
|
|
//if err != nil {
|
|
// return err
|
|
//}
|
|
|
|
return nil
|
|
}
|