344 lines
8.6 KiB
Go
344 lines
8.6 KiB
Go
package cmd
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"fmt"
|
|
|
|
"git.maurice.fr/thomas/mailout/pkg/crypto"
|
|
"git.maurice.fr/thomas/mailout/pkg/database"
|
|
"git.maurice.fr/thomas/mailout/pkg/models"
|
|
provider "git.maurice.fr/thomas/mailout/pkg/providers"
|
|
"github.com/google/uuid"
|
|
"github.com/pterm/pterm"
|
|
"github.com/sirupsen/logrus"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var (
|
|
flagDKIMKeyActive bool
|
|
flagSelector string
|
|
flagKeyBits int
|
|
flagProvider string
|
|
)
|
|
|
|
var DKIMKeyCmd = &cobra.Command{
|
|
Use: "dkimkey",
|
|
Short: "manages DKIM keys",
|
|
PreRunE: func(cmd *cobra.Command, args []string) error {
|
|
if flagProvider == "" {
|
|
if cfg.Defaults.Provider == "" {
|
|
logrus.Fatal("no provider specified and no default provider in config, aborting")
|
|
}
|
|
flagProvider = cfg.Defaults.Provider
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var DKIMKeyAddCmd = &cobra.Command{
|
|
Use: "add [domain]",
|
|
Short: "adds a DKIM signing key",
|
|
Args: cobra.ExactArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
db, err := database.NewDB(cfg)
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not connect to the database")
|
|
}
|
|
|
|
priv, pub, err := crypto.GenerateKeyPair(flagKeyBits)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
selector := flagSelector
|
|
if selector == "" {
|
|
b := make([]byte, 8)
|
|
_, err := rand.Read(b)
|
|
if err != nil {
|
|
logrus.Fatal("entropy generator is kill")
|
|
}
|
|
|
|
selector = hex.EncodeToString(b)
|
|
}
|
|
|
|
dkimkey := models.DKIMKey{
|
|
DomainName: args[0],
|
|
PublicKey: pub,
|
|
PrivateKey: priv,
|
|
Active: flagUserActive,
|
|
Selector: selector,
|
|
Record: fmt.Sprintf("%s._domainkey.%s. IN TXT \"v=DKIM1; k=rsa; p=%s\"", selector, args[0], pub),
|
|
}
|
|
err = db.Save(&dkimkey).Error
|
|
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not create DKIM key")
|
|
}
|
|
|
|
logrus.Infof("created DKIM key %s", dkimkey.ID)
|
|
},
|
|
}
|
|
|
|
var DKIMKeyListCmd = &cobra.Command{
|
|
Use: "list",
|
|
Short: "list DKIM keys",
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
db, err := database.NewDB(cfg)
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not connect to the database")
|
|
}
|
|
|
|
qRes := make([]models.DKIMKey, 0)
|
|
|
|
err = db.Find(&qRes).Error
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not list keys")
|
|
}
|
|
|
|
tData := pterm.TableData{
|
|
{"id", "selector", "domain", "active", "created_at", "updated_at"},
|
|
}
|
|
for _, k := range qRes {
|
|
tData = append(tData, []string{k.ID.String(), k.Selector, k.DomainName, fmt.Sprintf("%v", k.Active), k.CreatedAt.String(), k.UpdatedAt.String()})
|
|
}
|
|
|
|
pterm.DefaultTable.WithHasHeader().WithData(tData).Render()
|
|
},
|
|
}
|
|
|
|
var DKIMKeyRecordCmd = &cobra.Command{
|
|
Use: "record",
|
|
Short: "gives the dns record for a key",
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
db, err := database.NewDB(cfg)
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not connect to the database")
|
|
}
|
|
|
|
qRes := make([]models.DKIMKey, 0)
|
|
|
|
id, err := uuid.Parse(args[0])
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("invalid UUID")
|
|
}
|
|
|
|
err = db.Where(models.DKIMKey{ID: id}).Find(&qRes).Error
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not search keys")
|
|
}
|
|
if len(qRes) == 0 {
|
|
logrus.WithError(err).Fatal("No such key")
|
|
}
|
|
|
|
fmt.Println(qRes[0].Record)
|
|
},
|
|
}
|
|
|
|
var DKIMKeyDeleteCmd = &cobra.Command{
|
|
Use: "delete",
|
|
Short: "delete DKIM keys",
|
|
Args: cobra.ExactArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
db, err := database.NewDB(cfg)
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not connect to the database")
|
|
}
|
|
|
|
id, err := uuid.Parse(args[0])
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("invalid UUID")
|
|
}
|
|
err = db.Where(&models.DKIMKey{ID: id}).Delete(&models.DKIMKey{}).Error
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not delete DKIM key")
|
|
}
|
|
|
|
logrus.Infof("deleted DKIM key %s if it existed", args[0])
|
|
},
|
|
}
|
|
|
|
var DKIMKeyActivateCmd = &cobra.Command{
|
|
Use: "activate",
|
|
Short: "activates a DKIM key",
|
|
Args: cobra.ExactArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
db, err := database.NewDB(cfg)
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not connect to the database")
|
|
}
|
|
|
|
id, err := uuid.Parse(args[0])
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("invalid UUID")
|
|
}
|
|
|
|
err = db.Model(&models.DKIMKey{}).Where(&models.DKIMKey{ID: id}).Update("active", true).Error
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not activate DKIM key")
|
|
}
|
|
|
|
logrus.Infof("activated DKIM key %s", args[0])
|
|
},
|
|
}
|
|
|
|
var DKIMKeyDeactivateCmd = &cobra.Command{
|
|
Use: "deactivate",
|
|
Short: "deactivates a DKIM key",
|
|
Args: cobra.ExactArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
db, err := database.NewDB(cfg)
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not connect to the database")
|
|
}
|
|
|
|
id, err := uuid.Parse(args[0])
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("invalid UUID")
|
|
}
|
|
|
|
err = db.Model(&models.DKIMKey{}).Where(&models.DKIMKey{ID: id}).Update("active", false).Error
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not deactivate DKIM key")
|
|
}
|
|
|
|
logrus.Infof("deactivated DKIM key %s", args[0])
|
|
},
|
|
}
|
|
|
|
var DKIMKeyPublishCmd = &cobra.Command{
|
|
Use: "publish",
|
|
Short: "publishes a DKIM key onto a DNS provider",
|
|
Args: cobra.ExactArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
db, err := database.NewDB(cfg)
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not connect to the database")
|
|
}
|
|
|
|
qRes := make([]models.DKIMKey, 0)
|
|
|
|
id, err := uuid.Parse(args[0])
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("invalid UUID")
|
|
}
|
|
|
|
err = db.Where(models.DKIMKey{ID: id}).Find(&qRes).Error
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not get key")
|
|
}
|
|
if len(qRes) == 0 {
|
|
logrus.WithError(err).Fatal("No such key")
|
|
}
|
|
|
|
dkimkey := qRes[0]
|
|
logger := logrus.WithFields(logrus.Fields{
|
|
"dkimkey": dkimkey.ID,
|
|
"selector": dkimkey.Selector,
|
|
})
|
|
|
|
pv := flagProvider
|
|
if flagProvider == "" {
|
|
pv = cfg.Defaults.Provider
|
|
if pv == "" {
|
|
logrus.Fatal("no provider specified")
|
|
}
|
|
}
|
|
|
|
pGen, ok := provider.Providers[pv]
|
|
if !ok {
|
|
logger.Fatalf("no such provider: %s", flagProvider)
|
|
}
|
|
|
|
p, err := pGen(cfg)
|
|
if err != nil {
|
|
logger.WithError(err).Fatal("could not create provider")
|
|
}
|
|
|
|
err = p.AddDKIMRecord(&dkimkey)
|
|
if err != nil {
|
|
logger.WithError(err).Fatal("could not publish dkim key")
|
|
}
|
|
|
|
logger.Info("successfully published record")
|
|
},
|
|
}
|
|
|
|
var DKIMKeyUnpublishCmd = &cobra.Command{
|
|
Use: "unpublish",
|
|
Short: "removes a DKIM key onto a DNS provider",
|
|
Args: cobra.ExactArgs(1),
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
db, err := database.NewDB(cfg)
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not connect to the database")
|
|
}
|
|
|
|
qRes := make([]models.DKIMKey, 0)
|
|
|
|
id, err := uuid.Parse(args[0])
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("invalid UUID")
|
|
}
|
|
|
|
err = db.Where(models.DKIMKey{ID: id}).Find(&qRes).Error
|
|
if err != nil {
|
|
logrus.WithError(err).Fatal("could not get key")
|
|
}
|
|
if len(qRes) == 0 {
|
|
logrus.WithError(err).Fatal("No such key")
|
|
}
|
|
|
|
dkimkey := qRes[0]
|
|
|
|
logger := logrus.WithFields(logrus.Fields{
|
|
"dkimkey": dkimkey.ID,
|
|
"selector": dkimkey.Selector,
|
|
})
|
|
|
|
pv := flagProvider
|
|
if flagProvider == "" {
|
|
pv = cfg.Defaults.Provider
|
|
if pv == "" {
|
|
logrus.Fatal("no provider specified")
|
|
}
|
|
}
|
|
|
|
pGen, ok := provider.Providers[pv]
|
|
if !ok {
|
|
logger.Fatalf("no such provider: %s", flagProvider)
|
|
}
|
|
|
|
p, err := pGen(cfg)
|
|
if err != nil {
|
|
logger.WithError(err).Fatal("could not create provider")
|
|
}
|
|
|
|
err = p.DeleteDKIMRecord(&dkimkey)
|
|
if err != nil {
|
|
logger.WithError(err).Fatal("could not unpublish dkim key")
|
|
}
|
|
|
|
logger.Info("successfully unpublished record")
|
|
},
|
|
}
|
|
|
|
func InitDKIMKeyCmd() {
|
|
DKIMKeyCmd.AddCommand(DKIMKeyAddCmd)
|
|
DKIMKeyCmd.AddCommand(DKIMKeyListCmd)
|
|
DKIMKeyCmd.AddCommand(DKIMKeyDeleteCmd)
|
|
DKIMKeyCmd.AddCommand(DKIMKeyActivateCmd)
|
|
DKIMKeyCmd.AddCommand(DKIMKeyDeactivateCmd)
|
|
DKIMKeyCmd.AddCommand(DKIMKeyRecordCmd)
|
|
DKIMKeyCmd.AddCommand(DKIMKeyPublishCmd)
|
|
DKIMKeyCmd.AddCommand(DKIMKeyUnpublishCmd)
|
|
|
|
DKIMKeyAddCmd.PersistentFlags().BoolVarP(&flagDKIMKeyActive, "active", "a", true, "whether or not the created key is active")
|
|
DKIMKeyAddCmd.PersistentFlags().StringVarP(&flagSelector, "selector", "s", "", "force a selector for the key")
|
|
DKIMKeyAddCmd.PersistentFlags().IntVarP(&flagKeyBits, "key-bits", "k", 2048, "force a size for the key")
|
|
|
|
DKIMKeyPublishCmd.PersistentFlags().StringVarP(&flagProvider, "provider", "p", "", "provider to which publish the change to")
|
|
|
|
DKIMKeyUnpublishCmd.PersistentFlags().StringVarP(&flagProvider, "provider", "p", "", "provider to which unpublish the change from")
|
|
}
|