package main import ( "fmt" "log" "github.com/porter-dev/porter/cmd/migrate/keyrotate" adapter "github.com/porter-dev/porter/internal/adapter" "github.com/porter-dev/porter/internal/config" lr "github.com/porter-dev/porter/internal/logger" "github.com/porter-dev/porter/internal/models" ints "github.com/porter-dev/porter/internal/models/integrations" "github.com/joeshaw/envdecode" ) func main() { fmt.Println("running migrations...") appConf := config.FromEnv() logger := lr.NewConsole(true) db, err := adapter.New(&appConf.Db) if err != nil { logger.Fatal().Err(err).Msg("") return } err = db.AutoMigrate( &models.Project{}, &models.Role{}, &models.User{}, &models.Release{}, &models.Session{}, &models.GitRepo{}, &models.Registry{}, &models.HelmRepo{}, &models.Cluster{}, &models.ClusterCandidate{}, &models.ClusterResolver{}, &models.Infra{}, &models.GitActionConfig{}, &models.Invite{}, &models.AuthCode{}, &models.DNSRecord{}, &models.PWResetToken{}, &ints.KubeIntegration{}, &ints.BasicIntegration{}, &ints.OIDCIntegration{}, &ints.OAuthIntegration{}, &ints.GCPIntegration{}, &ints.AWSIntegration{}, &ints.TokenCache{}, &ints.ClusterTokenCache{}, &ints.RegTokenCache{}, &ints.HelmRepoTokenCache{}, ) if err != nil { panic(err) } if shouldRotate, oldKeyStr, newKeyStr := shouldKeyRotate(); shouldRotate { oldKey := [32]byte{} newKey := [32]byte{} copy(oldKey[:], []byte(oldKeyStr)) copy(newKey[:], []byte(newKeyStr)) err := keyrotate.Rotate(db, &oldKey, &newKey) if err != nil { panic(err) } } } type RotateConf struct { // we add a dummy field to avoid empty struct issue with envdecode DummyField string `env:"ASDF,default=asdf"` OldEncryptionKey string `env:"OLD_ENCRYPTION_KEY"` NewEncryptionKey string `env:"NEW_ENCRYPTION_KEY"` } func shouldKeyRotate() (bool, string, string) { var c RotateConf if err := envdecode.StrictDecode(&c); err != nil { log.Fatalf("Failed to decode migration conf: %s", err) return false, "", "" } return c.OldEncryptionKey != "" && c.NewEncryptionKey != "", c.OldEncryptionKey, c.NewEncryptionKey }