| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- //go:build ee
- // +build ee
- package migrate
- import (
- "fmt"
- "github.com/porter-dev/porter/api/server/shared/config/env"
- "github.com/porter-dev/porter/ee/integrations/vault"
- ints "github.com/porter-dev/porter/internal/models/integrations"
- "github.com/porter-dev/porter/internal/repository/credentials"
- "gorm.io/gorm"
- )
- // process 100 records at a time
- const stepSize = 100
- func MigrateVault(db *gorm.DB, dbConf *env.DBConf, shouldFinalize bool) error {
- var vaultClient *vault.Client
- if dbConf.VaultAPIKey != "" && dbConf.VaultServerURL != "" && dbConf.VaultPrefix != "" {
- vaultClient = vault.NewClient(
- dbConf.VaultServerURL,
- dbConf.VaultAPIKey,
- dbConf.VaultPrefix,
- )
- } else {
- return fmt.Errorf("env variables not properly set for vault migration")
- }
- err := migrateOAuthIntegrationModel(db, vaultClient, shouldFinalize)
- if err != nil {
- fmt.Printf("failed on oauth migration: %v\n", err)
- return err
- }
- err = migrateGCPIntegrationModel(db, vaultClient, shouldFinalize)
- if err != nil {
- fmt.Printf("failed on gcp migration: %v\n", err)
- return err
- }
- err = migrateAWSIntegrationModel(db, vaultClient, shouldFinalize)
- if err != nil {
- fmt.Printf("failed on aws migration: %v\n", err)
- return err
- }
- err = migrateGitlabIntegrationModel(db, vaultClient, shouldFinalize)
- if err != nil {
- fmt.Printf("failed on gitlab migration: %v\n", err)
- return err
- }
- return nil
- }
- func migrateOAuthIntegrationModel(db *gorm.DB, client *vault.Client, shouldFinalize bool) error {
- // get count of model
- var count int64
- if err := db.Model(&ints.OAuthIntegration{}).Count(&count).Error; err != nil {
- return err
- }
- // make a map of ids to errors -- we don't clear the integrations with errors
- errors := make(map[uint]error)
- // iterate (count / stepSize) + 1 times using Limit and Offset
- for i := 0; i < (int(count)/stepSize)+1; i++ {
- oauths := []*ints.OAuthIntegration{}
- if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&oauths).Error; err != nil {
- return err
- }
- // decrypt with the old key
- for _, oauth := range oauths {
- // Check if record already exists in vault client. If so, we don't write anything to vault,
- // since we don't want to overwrite any data that's been written.
- if resp, _ := client.GetOAuthCredential(oauth); resp != nil {
- continue
- }
- // write the data to the vault client
- if err := client.WriteOAuthCredential(oauth, &credentials.OAuthCredential{
- ClientID: oauth.ClientID,
- AccessToken: oauth.AccessToken,
- RefreshToken: oauth.RefreshToken,
- }); err != nil {
- errors[oauth.ID] = err
- fmt.Printf("oauth vault write error on ID %d: %v\n", oauth.ID, err)
- }
- }
- }
- fmt.Printf("migrated %d oauth integrations with %d errors\n", count, len(errors))
- if shouldFinalize {
- saveErrors := make(map[uint]error, 0)
- // iterate a second time, clearing the data
- // iterate (count / stepSize) + 1 times using Limit and Offset
- for i := 0; i < (int(count)/stepSize)+1; i++ {
- oauths := []*ints.OAuthIntegration{}
- if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&oauths).Error; err != nil {
- return err
- }
- // decrypt with the old key
- for _, oauth := range oauths {
- if _, found := errors[oauth.ID]; !found {
- // clear the data from the db, and save
- oauth.ClientID = []byte{}
- oauth.AccessToken = []byte{}
- oauth.RefreshToken = []byte{}
- if err := db.Save(oauth).Error; err != nil {
- saveErrors[oauth.ID] = err
- }
- }
- }
- }
- fmt.Printf("cleared %d oauth integrations with %d errors\n", count, len(saveErrors))
- for saveErrorID, saveError := range saveErrors {
- fmt.Printf("oauth save error on ID %d: %v\n", saveErrorID, saveError)
- }
- }
- return nil
- }
- func migrateGCPIntegrationModel(db *gorm.DB, client *vault.Client, shouldFinalize bool) error {
- // get count of model
- var count int64
- if err := db.Model(&ints.GCPIntegration{}).Count(&count).Error; err != nil {
- return err
- }
- // make a map of ids to errors -- we don't clear the integrations with errors
- errors := make(map[uint]error)
- // iterate (count / stepSize) + 1 times using Limit and Offset
- for i := 0; i < (int(count)/stepSize)+1; i++ {
- gcps := []*ints.GCPIntegration{}
- if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&gcps).Error; err != nil {
- return err
- }
- // decrypt with the old key
- for _, gcp := range gcps {
- // Check if record already exists in vault client. If so, we don't write anything to vault,
- // since we don't want to overwrite any data that's been written.
- if resp, _ := client.GetGCPCredential(gcp); resp != nil {
- continue
- }
- // write the data to the vault client
- if err := client.WriteGCPCredential(gcp, &credentials.GCPCredential{
- GCPKeyData: gcp.GCPKeyData,
- }); err != nil {
- errors[gcp.ID] = err
- fmt.Printf("gcp vault write error on ID %d: %v\n", gcp.ID, err)
- }
- }
- }
- fmt.Printf("migrated %d gcp integrations with %d errors\n", count, len(errors))
- if shouldFinalize {
- saveErrors := make(map[uint]error, 0)
- // iterate a second time, clearing the data
- // iterate (count / stepSize) + 1 times using Limit and Offset
- for i := 0; i < (int(count)/stepSize)+1; i++ {
- gcps := []*ints.GCPIntegration{}
- if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&gcps).Error; err != nil {
- return err
- }
- // decrypt with the old key
- for _, gcp := range gcps {
- if _, found := errors[gcp.ID]; !found {
- // clear the data from the db, and save
- gcp.GCPKeyData = []byte{}
- if err := db.Save(gcp).Error; err != nil {
- saveErrors[gcp.ID] = err
- }
- }
- }
- }
- fmt.Printf("cleared %d gcp integrations with %d errors\n", count, len(saveErrors))
- for saveErrorID, saveError := range saveErrors {
- fmt.Printf("gcp save error on ID %d: %v\n", saveErrorID, saveError)
- }
- }
- return nil
- }
- func migrateAWSIntegrationModel(db *gorm.DB, client *vault.Client, shouldFinalize bool) error {
- // get count of model
- var count int64
- if err := db.Model(&ints.AWSIntegration{}).Count(&count).Error; err != nil {
- return err
- }
- // make a map of ids to errors -- we don't clear the integrations with errors
- errors := make(map[uint]error)
- // iterate (count / stepSize) + 1 times using Limit and Offset
- for i := 0; i < (int(count)/stepSize)+1; i++ {
- awss := []*ints.AWSIntegration{}
- if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&awss).Error; err != nil {
- return err
- }
- // decrypt with the old key
- for _, aws := range awss {
- // Check if record already exists in vault client. If so, we don't write anything to vault,
- // since we don't want to overwrite any data that's been written.
- if resp, _ := client.GetAWSCredential(aws); resp != nil {
- continue
- }
- // write the data to the vault client
- if err := client.WriteAWSCredential(aws, &credentials.AWSCredential{
- AWSAccessKeyID: aws.AWSAccessKeyID,
- AWSClusterID: aws.AWSClusterID,
- AWSSecretAccessKey: aws.AWSSecretAccessKey,
- AWSSessionToken: aws.AWSSessionToken,
- }); err != nil {
- errors[aws.ID] = err
- fmt.Printf("aws vault write error on ID %d: %v\n", aws.ID, err)
- }
- }
- }
- fmt.Printf("migrated %d aws integrations with %d errors\n", count, len(errors))
- if shouldFinalize {
- saveErrors := make(map[uint]error, 0)
- // iterate a second time, clearing the data
- // iterate (count / stepSize) + 1 times using Limit and Offset
- for i := 0; i < (int(count)/stepSize)+1; i++ {
- awss := []*ints.AWSIntegration{}
- if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&awss).Error; err != nil {
- return err
- }
- // decrypt with the old key
- for _, aws := range awss {
- if _, found := errors[aws.ID]; !found {
- // clear the data from the db, and save
- aws.AWSAccessKeyID = []byte{}
- aws.AWSClusterID = []byte{}
- aws.AWSSecretAccessKey = []byte{}
- aws.AWSSessionToken = []byte{}
- if err := db.Save(aws).Error; err != nil {
- saveErrors[aws.ID] = err
- }
- }
- }
- }
- fmt.Printf("cleared %d aws integrations with %d errors\n", count, len(saveErrors))
- for saveErrorID, saveError := range saveErrors {
- fmt.Printf("aws save error on ID %d: %v\n", saveErrorID, saveError)
- }
- }
- return nil
- }
- func migrateGitlabIntegrationModel(db *gorm.DB, client *vault.Client, shouldFinalize bool) error {
- // get count of model
- var count int64
- if err := db.Model(&ints.GitlabIntegration{}).Count(&count).Error; err != nil {
- return err
- }
- // make a map of ids to errors -- we don't clear the integrations with errors
- errors := make(map[uint]error)
- // iterate (count / stepSize) + 1 times using Limit and Offset
- for i := 0; i < (int(count)/stepSize)+1; i++ {
- giInts := []*ints.GitlabIntegration{}
- if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&giInts).Error; err != nil {
- return err
- }
- // decrypt with the old key
- for _, gi := range giInts {
- // Check if record already exists in vault client. If so, we don't write anything to vault,
- // since we don't want to overwrite any data that's been written.
- if resp, _ := client.GetGitlabCredential(gi); resp != nil {
- continue
- }
- // write the data to the vault client
- if err := client.WriteGitlabCredential(gi, &credentials.GitlabCredential{
- AppClientID: gi.AppClientID,
- AppClientSecret: gi.AppClientSecret,
- }); err != nil {
- errors[gi.ID] = err
- fmt.Printf("gitlab vault write error on ID %d: %v\n", gi.ID, err)
- }
- }
- }
- fmt.Printf("migrated %d gitlab integrations with %d errors\n", count, len(errors))
- if shouldFinalize {
- saveErrors := make(map[uint]error, 0)
- // iterate a second time, clearing the data
- // iterate (count / stepSize) + 1 times using Limit and Offset
- for i := 0; i < (int(count)/stepSize)+1; i++ {
- giInts := []*ints.GitlabIntegration{}
- if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&giInts).Error; err != nil {
- return err
- }
- // decrypt with the old key
- for _, gi := range giInts {
- if _, found := errors[gi.ID]; !found {
- // clear the data from the db, and save
- gi.AppClientID = []byte{}
- gi.AppClientSecret = []byte{}
- if err := db.Save(gi).Error; err != nil {
- saveErrors[gi.ID] = err
- }
- }
- }
- }
- fmt.Printf("cleared %d gitlab integrations with %d errors\n", count, len(saveErrors))
- for saveErrorID, saveError := range saveErrors {
- fmt.Printf("gitlab save error on ID %d: %v\n", saveErrorID, saveError)
- }
- }
- return nil
- }
|