arcast/pkg/config/selfsigned.go

101 lines
2.2 KiB
Go

package config
import (
"context"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"fmt"
"slices"
"time"
"forge.cadoles.com/arcad/arcast/pkg/network"
"forge.cadoles.com/arcad/arcast/pkg/selfsigned"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/logger"
)
func GenerateSelfSignedCert(ctx context.Context, conf *Config) error {
if !conf.HTTPS.SelfSigned.Enabled {
return nil
}
if conf.HTTPS.Cert != nil && conf.HTTPS.Key != nil {
return nil
}
rawCert, rawKey, err := selfsigned.NewLANKeyPair()
if err != nil {
return errors.Wrap(err, "could not generate self signed x509 key pair")
}
conf.HTTPS.Cert = rawCert
conf.HTTPS.Key = rawKey
networkFingerprint, err := getNetworkFingerprint()
if err != nil {
return errors.Wrap(err, "could not retrieve network fingerprint")
}
conf.HTTPS.SelfSigned.NetworkFingerprint = networkFingerprint
return nil
}
func RenewExpiredSelfSignedCert(ctx context.Context, conf *Config) error {
if !conf.HTTPS.SelfSigned.Enabled {
return nil
}
if conf.HTTPS.Cert == nil || conf.HTTPS.Key == nil {
if err := GenerateSelfSignedCert(ctx, conf); err != nil {
return errors.WithStack(err)
}
}
cert, err := tls.X509KeyPair(conf.HTTPS.Cert, conf.HTTPS.Key)
if err != nil {
return errors.Wrap(err, "could not parse x509 cert/key pair")
}
leaf, err := x509.ParseCertificate(cert.Certificate[0])
if err != nil {
logger.Error(ctx, "could not parse x509 certificate, regenerating one", logger.CapturedE(errors.WithStack(err)))
if err := GenerateSelfSignedCert(ctx, conf); err != nil {
return errors.WithStack(err)
}
}
// Check that self-signed certificate is still valid
if time.Now().Before(leaf.NotAfter) {
return nil
}
logger.Warn(ctx, "self-signed certificate has expired, regenerating one", logger.CapturedE(errors.WithStack(err)))
if err := GenerateSelfSignedCert(ctx, conf); err != nil {
return errors.WithStack(err)
}
return nil
}
func getNetworkFingerprint() (string, error) {
ips, err := network.GetLANIPv4Addrs()
if err != nil {
return "", errors.WithStack(err)
}
slices.Sort(ips)
hash := sha256.New()
for _, ip := range ips {
if _, err := hash.Write([]byte(ip)); err != nil {
return "", errors.WithStack(err)
}
}
return fmt.Sprintf("%x", hash.Sum(nil)), nil
}