M internal/db/domains.go => internal/db/domains.go +10 -0
@@ 219,3 219,13 @@ func FetchDomainTsigKey(ddnsDomain string) (string, error) {
}
return tsig, nil
}
+
+// RefreshDomainTsigKey refreshes the Tsig key of a domain.
+func RefreshDomainTsigKey(id string, userID string) error {
+ tsigKey := util.GenTsigKey()
+ _, err := DBConn.Exec(`UPDATE domains SET tsigkey = $1 WHERE id = $2 AND owner = $3`, tsigKey, id, userID)
+ if err != nil {
+ return err
+ }
+ return nil
+}
M internal/handlers/domains.go => internal/handlers/domains.go +24 -0
@@ 152,3 152,27 @@ func RefreshDomainAPIKey() gin.HandlerFunc {
c.Header("HX-Trigger", "update-domain-list")
}
}
+
+// RefreshDomainTsigKey returns a gin handler
+func RefreshDomainTsigKey() gin.HandlerFunc {
+ return func(c *gin.Context) {
+ id := c.Param("id")
+
+ userID, exists := c.Get("user_id")
+ if !exists {
+ c.String(http.StatusInternalServerError, "This should not be possible, but don't quote me on that")
+ c.Abort()
+ return
+ }
+
+ err := db.RefreshDomainTsigKey(id, userID.(string))
+ if err != nil {
+ // FIXME: Handle better
+ c.String(http.StatusInternalServerError, "Something went wrong while updating the tsig key")
+ c.Abort()
+ return
+ }
+
+ c.Header("HX-Trigger", "update-domain-list")
+ }
+}
M internal/routers/frontend.go => internal/routers/frontend.go +1 -0
@@ 49,6 49,7 @@ func SetupFrontendRouter(sm *scs.SessionManager) *gin.Engine {
manage.PATCH("/domains/:id", handlers.PatchDomain())
manage.DELETE("/domains/:id", handlers.DeleteDomain())
manage.POST("/domains/:id/api_key", handlers.RefreshDomainAPIKey())
+ manage.POST("/domains/:id/tsig_key", handlers.RefreshDomainTsigKey())
manage.GET("/partials/domains", handlers.ManagePartialDomains())
}
A internal/util/gentsigkey.go => internal/util/gentsigkey.go +24 -0
@@ 0,0 1,24 @@
+/*
+ * Copyright (C) 2024 Jonni Liljamo <jonni@liljamo.com>
+ *
+ * This file is licensed under AGPL-3.0-or-later, see NOTICE and LICENSE for
+ * more information.
+ */
+
+package util
+
+import (
+ "encoding/base64"
+ "math/rand"
+)
+
+const charsTsigKey = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%&*()+=_-'\"\\][{}/?"
+
+// GenTsigKey returns a base64 tsig shared secret.
+func GenTsigKey() string {
+ b := make([]byte, 32)
+ for i := range b {
+ b[i] = charsTsigKey[rand.Int63()%int64(len(charsTsigKey))]
+ }
+ return base64.StdEncoding.EncodeToString(b)
+}