mirror of
https://github.com/outbackdingo/labca.git
synced 2026-01-27 10:19:34 +00:00
195 lines
5.1 KiB
Go
195 lines
5.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
func CheckUpgrades() {
|
|
v := viper.GetString("version")
|
|
if standaloneVersion == "" {
|
|
gitVersion := controlCommand("git-version", true)
|
|
if gitVersion != "" {
|
|
viper.Set("version", strings.TrimSpace(gitVersion))
|
|
_ = viper.WriteConfig()
|
|
}
|
|
} else if v != standaloneVersion {
|
|
viper.Set("version", standaloneVersion)
|
|
_ = viper.WriteConfig()
|
|
}
|
|
|
|
changed := CheckUpgrade_01_CeremonyHSM()
|
|
|
|
if changed {
|
|
time.Sleep(2 * time.Second)
|
|
log.Println("Applying updated configuration...")
|
|
controlCommand("apply", false)
|
|
time.Sleep(2 * time.Second)
|
|
log.Println("Updating CRL links if needed...")
|
|
controlCommand("check-crl", false)
|
|
time.Sleep(2 * time.Second)
|
|
log.Println("Restarting boulder containers...")
|
|
controlCommand("boulder-restart", false)
|
|
}
|
|
}
|
|
|
|
func readFileAsString(filename string) string {
|
|
read, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
log.Printf("**** Could not read '%s': %s\n", filename, err.Error())
|
|
log.Println("**** ABORT MIGRATION ****")
|
|
time.Sleep(1 * time.Minute)
|
|
os.Exit(1)
|
|
}
|
|
|
|
return string(read)
|
|
}
|
|
|
|
func controlCommand(command string, ignoreError bool) string {
|
|
conn, err := net.Dial("tcp", "control:3030")
|
|
if err != nil {
|
|
if ignoreError {
|
|
return ""
|
|
}
|
|
log.Println("**** Failed to connect to control container!")
|
|
time.Sleep(1 * time.Minute)
|
|
os.Exit(1)
|
|
}
|
|
defer func() { _ = conn.Close() }()
|
|
|
|
_, _ = fmt.Fprint(conn, command+"\n")
|
|
|
|
reader := bufio.NewReader(conn)
|
|
message, err := io.ReadAll(reader)
|
|
if err != nil {
|
|
log.Printf("**** Failed to read response from control container: %s\n", err.Error())
|
|
time.Sleep(1 * time.Minute)
|
|
os.Exit(1)
|
|
}
|
|
|
|
if len(message) >= 4 {
|
|
tail := message[len(message)-4:]
|
|
if strings.Compare(string(tail), "\nok\n") == 0 {
|
|
msg := message[0 : len(message)-4]
|
|
log.Printf("**** Message from control server: '%s'", msg)
|
|
}
|
|
}
|
|
|
|
return string(message)
|
|
}
|
|
|
|
func copyFile(src, dst string) error {
|
|
sourceFile, err := os.Open(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() { _ = sourceFile.Close() }()
|
|
|
|
destinationFile, err := os.Create(dst)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer func() { _ = destinationFile.Close() }()
|
|
|
|
_, err = io.Copy(destinationFile, sourceFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = destinationFile.Sync()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Check if we should upgrade to using the Ceremony tool and store keys on SoftHSM (January 2025).
|
|
func CheckUpgrade_01_CeremonyHSM() bool {
|
|
baseDir := "/opt/labca/data/"
|
|
prevRootCert := baseDir + "root-ca.pem"
|
|
if _, err := os.Stat(prevRootCert); errors.Is(err, fs.ErrNotExist) {
|
|
baseDir = "/go/src/labca/data/"
|
|
prevRootCert = baseDir + "root-ca.pem"
|
|
if _, err := os.Stat(prevRootCert); errors.Is(err, fs.ErrNotExist) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
log.Println("**** BEGIN MIGRATION: upgrade01 ****")
|
|
|
|
rootCertFile := fmt.Sprintf("%sroot-01-cert.pem", CERT_FILES_PATH)
|
|
if _, err := os.Stat(rootCertFile); !errors.Is(err, fs.ErrNotExist) {
|
|
log.Printf("**** File %s already exists!\n", rootCertFile)
|
|
log.Println("**** ABORT MIGRATION ****")
|
|
time.Sleep(1 * time.Minute)
|
|
os.Exit(1)
|
|
}
|
|
|
|
prevRootKey := baseDir + "root-ca.key"
|
|
if _, err := os.Stat(prevRootKey); errors.Is(err, fs.ErrNotExist) {
|
|
log.Println("**** Root key file not present on the system: cannot upgrade automatically!")
|
|
log.Println("**** Please do a fresh install of LabCA and import / upload the root certificate and key.")
|
|
log.Println("**** ABORT MIGRATION ****")
|
|
time.Sleep(1 * time.Minute)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Migrate root certificate and key
|
|
ci := &CertificateInfo{IsRoot: true}
|
|
ci.Initialize()
|
|
ci.IsRoot = true
|
|
ci.CreateType = "upload"
|
|
ci.Certificate = readFileAsString(prevRootCert)
|
|
ci.Key = readFileAsString(prevRootKey)
|
|
prevRootCRL := baseDir + "root-ca.crl"
|
|
if _, err := os.Stat(prevRootCRL); !errors.Is(err, fs.ErrNotExist) {
|
|
ci.CRL = readFileAsString(prevRootCRL)
|
|
_ = copyFile(prevRootCRL, strings.ReplaceAll(rootCertFile, "-cert.", "-crl."))
|
|
}
|
|
|
|
if err := ci.Create("root-01", false); err != nil {
|
|
log.Printf("**** Could not convert previous root certificate and key: %s\n", err.Error())
|
|
log.Println("**** ABORT MIGRATION ****")
|
|
time.Sleep(1 * time.Minute)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Migrate issuer certificate and key
|
|
ci = &CertificateInfo{IsRoot: false}
|
|
ci.Initialize()
|
|
ci.IsRoot = false
|
|
ci.CreateType = "upload"
|
|
prevIssuerCert := baseDir + "issuer/ca-int.pem"
|
|
ci.Certificate = readFileAsString(prevIssuerCert)
|
|
prevIssuerKey := baseDir + "issuer/ca-int.key"
|
|
ci.Key = readFileAsString(prevIssuerKey)
|
|
ci.CRL = ""
|
|
|
|
if err := ci.Create("issuer-01", false); err != nil {
|
|
log.Printf("**** Could not convert previous issuer certificate and key: %s\n", err.Error())
|
|
log.Println("**** ABORT MIGRATION ****")
|
|
time.Sleep(1 * time.Minute)
|
|
os.Exit(1)
|
|
}
|
|
|
|
_ = os.Rename(prevRootCert, prevRootCert+"_backup")
|
|
_ = os.Rename(prevRootKey, prevRootKey+"_backup")
|
|
_ = os.Rename(prevRootCRL, prevRootCRL+"_backup")
|
|
_ = os.Rename(prevIssuerCert, prevIssuerCert+"_backup")
|
|
_ = os.Rename(prevIssuerKey, prevIssuerKey+"_backup")
|
|
|
|
log.Println("**** END MIGRATION ****")
|
|
return true
|
|
}
|