Generate VAPID key pair during startup

This commit is contained in:
Vyr Cossont 2024-11-23 20:32:55 -08:00
parent 7a02a19c3c
commit 821c1da688
4 changed files with 59 additions and 25 deletions

View File

@ -30,6 +30,7 @@
"time" "time"
"github.com/KimMachineGun/automemlimit/memlimit" "github.com/KimMachineGun/automemlimit/memlimit"
webpushgo "github.com/SherClockHolmes/webpush-go"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action" "github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action"
"github.com/superseriousbusiness/gotosocial/internal/admin" "github.com/superseriousbusiness/gotosocial/internal/admin"
@ -40,6 +41,7 @@
"github.com/superseriousbusiness/gotosocial/internal/filter/spam" "github.com/superseriousbusiness/gotosocial/internal/filter/spam"
"github.com/superseriousbusiness/gotosocial/internal/filter/visibility" "github.com/superseriousbusiness/gotosocial/internal/filter/visibility"
"github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/media/ffmpeg" "github.com/superseriousbusiness/gotosocial/internal/media/ffmpeg"
"github.com/superseriousbusiness/gotosocial/internal/messages" "github.com/superseriousbusiness/gotosocial/internal/messages"
"github.com/superseriousbusiness/gotosocial/internal/metrics" "github.com/superseriousbusiness/gotosocial/internal/metrics"
@ -248,6 +250,22 @@
} }
} }
// Get or create a VAPID key pair.
vapidKeyPair, err := dbService.GetVAPIDKeyPair(ctx)
if err != nil {
return gtserror.Newf("error getting VAPID key pair: %w", err)
}
if vapidKeyPair == nil {
// Generate and store a new key pair.
vapidKeyPair = &gtsmodel.VAPIDKeyPair{}
if vapidKeyPair.Private, vapidKeyPair.Public, err = webpushgo.GenerateVAPIDKeys(); err != nil {
return gtserror.Newf("error generating VAPID key pair: %w", err)
}
if err := dbService.PutVAPIDKeyPair(ctx, vapidKeyPair); err != nil {
return gtserror.Newf("error putting VAPID key pair: %w", err)
}
}
// Initialize both home / list timelines. // Initialize both home / list timelines.
state.Timelines.Home = timeline.NewManager( state.Timelines.Home = timeline.NewManager(
tlprocessor.HomeTimelineGrab(state), tlprocessor.HomeTimelineGrab(state),

View File

@ -68,9 +68,13 @@ type Admin interface {
// the number of pending sign-ups sitting in the backlog. // the number of pending sign-ups sitting in the backlog.
CountUnhandledSignups(ctx context.Context) (int, error) CountUnhandledSignups(ctx context.Context) (int, error)
// GetOrCreateVAPIDKeyPair creates and stores a VAPID key pair, // GetVAPIDKeyPair retrieves the existing VAPID key pair, if there is one.
// or retrieves the existing VAPID key pair. // If there isn't, it returns nil.
GetOrCreateVAPIDKeyPair(ctx context.Context) (*gtsmodel.VAPIDKeyPair, error) GetVAPIDKeyPair(ctx context.Context) (*gtsmodel.VAPIDKeyPair, error)
// PutVAPIDKeyPair stores a VAPID key pair.
// This should be called at most once, during server startup.
PutVAPIDKeyPair(ctx context.Context, vapidKeyPair *gtsmodel.VAPIDKeyPair) error
/* /*
ACTION FUNCS ACTION FUNCS

View File

@ -27,7 +27,6 @@
"strings" "strings"
"time" "time"
webpushgo "github.com/SherClockHolmes/webpush-go"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/superseriousbusiness/gotosocial/internal/ap" "github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/config" "github.com/superseriousbusiness/gotosocial/internal/config"
@ -49,6 +48,9 @@
type adminDB struct { type adminDB struct {
db *bun.DB db *bun.DB
state *state.State state *state.State
// Since the VAPID key pair is very small and never written to concurrently, we can cache it here.
vapidKeyPair *gtsmodel.VAPIDKeyPair
} }
func (a *adminDB) IsUsernameAvailable(ctx context.Context, username string) (bool, error) { func (a *adminDB) IsUsernameAvailable(ctx context.Context, username string) (bool, error) {
@ -443,36 +445,37 @@ func (a *adminDB) CountUnhandledSignups(ctx context.Context) (int, error) {
Count(ctx) Count(ctx)
} }
func (a *adminDB) GetOrCreateVAPIDKeyPair(ctx context.Context) (*gtsmodel.VAPIDKeyPair, error) { func (a *adminDB) GetVAPIDKeyPair(ctx context.Context) (*gtsmodel.VAPIDKeyPair, error) {
var err error // Look for cached keys.
var vapidKeyPair *gtsmodel.VAPIDKeyPair if a.vapidKeyPair != nil {
return a.vapidKeyPair, nil
}
// Look for previously generated keys. // Look for previously generated keys in the database.
if err = a.db.NewSelect(). if err := a.db.NewSelect().
Model(vapidKeyPair). Model(a.vapidKeyPair).
Limit(1). Limit(1).
Scan(ctx); // nocollapse Scan(ctx); // nocollapse
err != nil && !errors.Is(err, db.ErrNoEntries) { err != nil && !errors.Is(err, db.ErrNoEntries) {
return nil, gtserror.Newf("DB error getting VAPID key pair: %w", err) return nil, gtserror.Newf("DB error getting VAPID key pair: %w", err)
} }
if vapidKeyPair == nil { return a.vapidKeyPair, nil
// Generate new keys. }
vapidKeyPair = &gtsmodel.VAPIDKeyPair{}
if vapidKeyPair.Private, vapidKeyPair.Public, err = webpushgo.GenerateVAPIDKeys(); err != nil {
return nil, gtserror.Newf("error generating VAPID key pair: %w", err)
}
// Save them to the database. func (a *adminDB) PutVAPIDKeyPair(ctx context.Context, vapidKeyPair *gtsmodel.VAPIDKeyPair) error {
if _, err = a.db.NewInsert(). // Store the keys in the database.
Model(vapidKeyPair). if _, err := a.db.NewInsert().
Exec(ctx); // nocollapse Model(a.vapidKeyPair).
err != nil { Exec(ctx); // nocollapse
return nil, gtserror.Newf("DB error saving VAPID key pair: %w", err) err != nil {
} return gtserror.Newf("DB error putting VAPID key pair: %w", err)
} }
return vapidKeyPair, err // Cache the keys.
a.vapidKeyPair = vapidKeyPair
return nil
} }
/* /*

View File

@ -19,7 +19,7 @@
import ( import (
"context" "context"
webpushgo "github.com/SherClockHolmes/webpush-go"
"github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb" "github.com/superseriousbusiness/gotosocial/internal/db/bundb"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
@ -368,6 +368,15 @@ func StandardDBSetup(db db.DB, accounts map[string]*gtsmodel.Account) {
log.Panic(ctx, err) log.Panic(ctx, err)
} }
vapidKeyPair := &gtsmodel.VAPIDKeyPair{}
var err error
if vapidKeyPair.Private, vapidKeyPair.Public, err = webpushgo.GenerateVAPIDKeys(); err != nil {
log.Panic(nil, err)
}
if err = db.PutVAPIDKeyPair(ctx, vapidKeyPair); err != nil {
log.Panic(nil, err)
}
log.Debug(ctx, "testing db setup complete") log.Debug(ctx, "testing db setup complete")
} }