rotate.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. package keyrotate
  2. import (
  3. "fmt"
  4. "encoding/hex"
  5. "github.com/porter-dev/porter/internal/models"
  6. ints "github.com/porter-dev/porter/internal/models/integrations"
  7. gorm "github.com/porter-dev/porter/internal/repository/gorm"
  8. _gorm "gorm.io/gorm"
  9. )
  10. // process 100 records at a time
  11. const stepSize = 100
  12. func Rotate(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  13. oldKeyBytes := make([]byte, 32)
  14. newKeyBytes := make([]byte, 32)
  15. copy(oldKeyBytes[:], oldKey[:])
  16. copy(newKeyBytes[:], newKey[:])
  17. err := rotateClusterModel(db, oldKey, newKey)
  18. if err != nil {
  19. fmt.Printf("failed on cluster rotation: %v\n", err)
  20. return err
  21. }
  22. err = rotateClusterCandidateModel(db, oldKey, newKey)
  23. if err != nil {
  24. fmt.Printf("failed on cc rotation: %v\n", err)
  25. return err
  26. }
  27. err = rotateRegistryModel(db, oldKey, newKey)
  28. if err != nil {
  29. fmt.Printf("failed on registry rotation: %v\n", err)
  30. return err
  31. }
  32. err = rotateHelmRepoModel(db, oldKey, newKey)
  33. if err != nil {
  34. fmt.Printf("failed on hr rotation: %v\n", err)
  35. return err
  36. }
  37. err = rotateInfraModel(db, oldKey, newKey)
  38. if err != nil {
  39. fmt.Printf("failed on infra rotation: %v\n", err)
  40. return err
  41. }
  42. err = rotateKubeIntegrationModel(db, oldKey, newKey)
  43. if err != nil {
  44. fmt.Printf("failed on ki rotation: %v\n", err)
  45. return err
  46. }
  47. err = rotateBasicIntegrationModel(db, oldKey, newKey)
  48. if err != nil {
  49. fmt.Printf("failed on basic rotation: %v\n", err)
  50. return err
  51. }
  52. err = rotateOIDCIntegrationModel(db, oldKey, newKey)
  53. if err != nil {
  54. fmt.Printf("failed on oidc rotation: %v\n", err)
  55. return err
  56. }
  57. err = rotateOAuthIntegrationModel(db, oldKey, newKey)
  58. if err != nil {
  59. fmt.Printf("failed on oauth rotation: %v\n", err)
  60. return err
  61. }
  62. err = rotateGCPIntegrationModel(db, oldKey, newKey)
  63. if err != nil {
  64. fmt.Printf("failed on gcp rotation: %v\n", err)
  65. return err
  66. }
  67. err = rotateAWSIntegrationModel(db, oldKey, newKey)
  68. if err != nil {
  69. fmt.Printf("failed on aws rotation: %v\n", err)
  70. return err
  71. }
  72. return nil
  73. }
  74. func rotateClusterModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  75. // get count of model
  76. var count int64
  77. if err := db.Model(&models.Cluster{}).Count(&count).Error; err != nil {
  78. return err
  79. }
  80. // cluster-scoped repository
  81. repo := gorm.NewClusterRepository(db, oldKey).(*gorm.ClusterRepository)
  82. // iterate (count / stepSize) + 1 times using Limit and Offset
  83. for i := 0; i < (int(count)/stepSize)+1; i++ {
  84. clusters := []*models.Cluster{}
  85. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Preload("TokenCache").Find(&clusters).Error; err != nil {
  86. return err
  87. }
  88. // decrypt with the old key
  89. for _, cluster := range clusters {
  90. err := repo.DecryptClusterData(cluster, oldKey)
  91. if err != nil {
  92. return err
  93. }
  94. if err != nil {
  95. fmt.Printf("error decrypting cluster %d\n", cluster.ID)
  96. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  97. // recover it
  98. cluster.CertificateAuthorityData = []byte{}
  99. cluster.TokenCache.Token = []byte{}
  100. }
  101. }
  102. // encrypt with the new key and re-insert
  103. for _, cluster := range clusters {
  104. err := repo.EncryptClusterData(cluster, newKey)
  105. if err != nil {
  106. fmt.Printf("error encrypting cluster %d\n", cluster.ID)
  107. return err
  108. }
  109. if err := db.Save(cluster).Error; err != nil {
  110. return err
  111. }
  112. }
  113. }
  114. fmt.Printf("rotated %d clusters\n", count)
  115. return nil
  116. }
  117. func rotateClusterCandidateModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  118. // get count of model
  119. var count int64
  120. if err := db.Model(&models.ClusterCandidate{}).Count(&count).Error; err != nil {
  121. return err
  122. }
  123. // cluster-scoped repository
  124. repo := gorm.NewClusterRepository(db, oldKey).(*gorm.ClusterRepository)
  125. // iterate (count / stepSize) + 1 times using Limit and Offset
  126. for i := 0; i < (int(count)/stepSize)+1; i++ {
  127. ccs := []*models.ClusterCandidate{}
  128. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&ccs).Error; err != nil {
  129. return err
  130. }
  131. // decrypt with the old key
  132. for _, cc := range ccs {
  133. err := repo.DecryptClusterCandidateData(cc, oldKey)
  134. if err != nil {
  135. fmt.Printf("error decrypting cluster candidate %d\n", cc.ID)
  136. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  137. // recover it
  138. cc.AWSClusterIDGuess = []byte{}
  139. cc.Kubeconfig = []byte{}
  140. }
  141. }
  142. // encrypt with the new key and re-insert
  143. for _, cc := range ccs {
  144. err := repo.EncryptClusterCandidateData(cc, newKey)
  145. if err != nil {
  146. fmt.Printf("error encrypting cluster candidate %d\n", cc.ID)
  147. return err
  148. }
  149. if err := db.Save(cc).Error; err != nil {
  150. return err
  151. }
  152. }
  153. }
  154. fmt.Printf("rotated %d cluster candidates\n", count)
  155. return nil
  156. }
  157. func rotateRegistryModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  158. // get count of model
  159. var count int64
  160. if err := db.Model(&models.Registry{}).Count(&count).Error; err != nil {
  161. return err
  162. }
  163. // registry-scoped repository
  164. repo := gorm.NewRegistryRepository(db, oldKey).(*gorm.RegistryRepository)
  165. // iterate (count / stepSize) + 1 times using Limit and Offset
  166. for i := 0; i < (int(count)/stepSize)+1; i++ {
  167. regs := []*models.Registry{}
  168. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Preload("TokenCache").Find(&regs).Error; err != nil {
  169. return err
  170. }
  171. // decrypt with the old key
  172. for _, reg := range regs {
  173. err := repo.DecryptRegistryData(reg, oldKey)
  174. if err != nil {
  175. fmt.Printf("error decrypting registry %d\n", reg.ID)
  176. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  177. // recover it
  178. reg.TokenCache.Token = []byte{}
  179. }
  180. }
  181. // encrypt with the new key and re-insert
  182. for _, reg := range regs {
  183. err := repo.EncryptRegistryData(reg, newKey)
  184. if err != nil {
  185. fmt.Printf("error encrypting registry %d\n", reg.ID)
  186. return err
  187. }
  188. if err := db.Save(reg).Error; err != nil {
  189. return err
  190. }
  191. }
  192. }
  193. fmt.Printf("rotated %d registries\n", count)
  194. return nil
  195. }
  196. func rotateHelmRepoModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  197. // get count of model
  198. var count int64
  199. if err := db.Model(&models.HelmRepo{}).Count(&count).Error; err != nil {
  200. return err
  201. }
  202. // helm repo-scoped repository
  203. repo := gorm.NewHelmRepoRepository(db, oldKey).(*gorm.HelmRepoRepository)
  204. // iterate (count / stepSize) + 1 times using Limit and Offset
  205. for i := 0; i < (int(count)/stepSize)+1; i++ {
  206. hrs := []*models.HelmRepo{}
  207. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Preload("TokenCache").Find(&hrs).Error; err != nil {
  208. return err
  209. }
  210. // decrypt with the old key
  211. for _, hr := range hrs {
  212. err := repo.DecryptHelmRepoData(hr, oldKey)
  213. if err != nil {
  214. fmt.Printf("error decrypting helm repo %d\n", hr.ID)
  215. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  216. // recover it
  217. hr.TokenCache.Token = []byte{}
  218. }
  219. }
  220. // encrypt with the new key and re-insert
  221. for _, hr := range hrs {
  222. err := repo.EncryptHelmRepoData(hr, newKey)
  223. if err != nil {
  224. fmt.Printf("error encrypting helm repo %d\n", hr.ID)
  225. return err
  226. }
  227. if err := db.Save(hr).Error; err != nil {
  228. return err
  229. }
  230. }
  231. }
  232. fmt.Printf("rotated %d helm repos\n", count)
  233. return nil
  234. }
  235. func rotateInfraModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  236. // get count of model
  237. var count int64
  238. if err := db.Model(&models.Infra{}).Count(&count).Error; err != nil {
  239. return err
  240. }
  241. // helm repo-scoped repository
  242. repo := gorm.NewInfraRepository(db, oldKey).(*gorm.InfraRepository)
  243. // iterate (count / stepSize) + 1 times using Limit and Offset
  244. for i := 0; i < (int(count)/stepSize)+1; i++ {
  245. infras := []*models.Infra{}
  246. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&infras).Error; err != nil {
  247. return err
  248. }
  249. // decrypt with the old key
  250. for _, infra := range infras {
  251. err := repo.DecryptInfraData(infra, oldKey)
  252. if err != nil {
  253. oldKeyBytes := make([]byte, 32)
  254. newKeyBytes := make([]byte, 32)
  255. copy(oldKeyBytes[:], oldKey[:])
  256. copy(newKeyBytes[:], newKey[:])
  257. fmt.Printf("error decrypting infra %d, %s, %s, %s\n", infra.ID, hex.EncodeToString(infra.LastApplied), string(oldKeyBytes), string(newKeyBytes))
  258. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  259. // recover it
  260. infra.LastApplied = []byte{}
  261. }
  262. }
  263. // encrypt with the new key and re-insert
  264. for _, infra := range infras {
  265. err := repo.EncryptInfraData(infra, newKey)
  266. if err != nil {
  267. fmt.Printf("error encrypting infra %d\n", infra.ID)
  268. return err
  269. }
  270. if err := db.Save(infra).Error; err != nil {
  271. return err
  272. }
  273. }
  274. }
  275. fmt.Printf("rotated %d infras\n", count)
  276. return nil
  277. }
  278. func rotateKubeIntegrationModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  279. // get count of model
  280. var count int64
  281. if err := db.Model(&ints.KubeIntegration{}).Count(&count).Error; err != nil {
  282. return err
  283. }
  284. // cluster-scoped repository
  285. repo := gorm.NewKubeIntegrationRepository(db, oldKey).(*gorm.KubeIntegrationRepository)
  286. // iterate (count / stepSize) + 1 times using Limit and Offset
  287. for i := 0; i < (int(count)/stepSize)+1; i++ {
  288. kis := []*ints.KubeIntegration{}
  289. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&kis).Error; err != nil {
  290. return err
  291. }
  292. // decrypt with the old key
  293. for _, ki := range kis {
  294. err := repo.DecryptKubeIntegrationData(ki, oldKey)
  295. if err != nil {
  296. fmt.Printf("error decrypting kube integration %d\n", ki.ID)
  297. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  298. // recover it
  299. ki.ClientCertificateData = []byte{}
  300. ki.ClientKeyData = []byte{}
  301. ki.Token = []byte{}
  302. ki.Username = []byte{}
  303. ki.Password = []byte{}
  304. ki.Kubeconfig = []byte{}
  305. }
  306. }
  307. // encrypt with the new key and re-insert
  308. for _, ki := range kis {
  309. err := repo.EncryptKubeIntegrationData(ki, newKey)
  310. if err != nil {
  311. fmt.Printf("error encrypting kube integration %d\n", ki.ID)
  312. return err
  313. }
  314. if err := db.Save(ki).Error; err != nil {
  315. return err
  316. }
  317. }
  318. }
  319. fmt.Printf("rotated %d kube integrations\n", count)
  320. return nil
  321. }
  322. func rotateBasicIntegrationModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  323. // get count of model
  324. var count int64
  325. if err := db.Model(&ints.BasicIntegration{}).Count(&count).Error; err != nil {
  326. return err
  327. }
  328. // cluster-scoped repository
  329. repo := gorm.NewBasicIntegrationRepository(db, oldKey).(*gorm.BasicIntegrationRepository)
  330. // iterate (count / stepSize) + 1 times using Limit and Offset
  331. for i := 0; i < (int(count)/stepSize)+1; i++ {
  332. basics := []*ints.BasicIntegration{}
  333. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&basics).Error; err != nil {
  334. return err
  335. }
  336. // decrypt with the old key
  337. for _, basic := range basics {
  338. err := repo.DecryptBasicIntegrationData(basic, oldKey)
  339. if err != nil {
  340. fmt.Printf("error decrypting basic integration %d\n", basic.ID)
  341. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  342. // recover it
  343. basic.Username = []byte{}
  344. basic.Password = []byte{}
  345. }
  346. }
  347. // encrypt with the new key and re-insert
  348. for _, basic := range basics {
  349. err := repo.EncryptBasicIntegrationData(basic, newKey)
  350. if err != nil {
  351. fmt.Printf("error encrypting basic integration %d\n", basic.ID)
  352. return err
  353. }
  354. if err := db.Save(basic).Error; err != nil {
  355. return err
  356. }
  357. }
  358. }
  359. fmt.Printf("rotated %d basic integrations\n", count)
  360. return nil
  361. }
  362. func rotateOIDCIntegrationModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  363. // get count of model
  364. var count int64
  365. if err := db.Model(&ints.OIDCIntegration{}).Count(&count).Error; err != nil {
  366. return err
  367. }
  368. // cluster-scoped repository
  369. repo := gorm.NewOIDCIntegrationRepository(db, oldKey).(*gorm.OIDCIntegrationRepository)
  370. // iterate (count / stepSize) + 1 times using Limit and Offset
  371. for i := 0; i < (int(count)/stepSize)+1; i++ {
  372. oidcs := []*ints.OIDCIntegration{}
  373. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&oidcs).Error; err != nil {
  374. return err
  375. }
  376. // decrypt with the old key
  377. for _, oidc := range oidcs {
  378. err := repo.DecryptOIDCIntegrationData(oidc, oldKey)
  379. if err != nil {
  380. fmt.Printf("error decrypting oidc integration %d\n", oidc.ID)
  381. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  382. // recover it
  383. oidc.IssuerURL = []byte{}
  384. oidc.ClientID = []byte{}
  385. oidc.ClientSecret = []byte{}
  386. oidc.CertificateAuthorityData = []byte{}
  387. oidc.IDToken = []byte{}
  388. oidc.RefreshToken = []byte{}
  389. }
  390. }
  391. // encrypt with the new key and re-insert
  392. for _, oidc := range oidcs {
  393. err := repo.EncryptOIDCIntegrationData(oidc, newKey)
  394. if err != nil {
  395. fmt.Printf("error encrypting oidc integration %d\n", oidc.ID)
  396. return err
  397. }
  398. if err := db.Save(oidc).Error; err != nil {
  399. return err
  400. }
  401. }
  402. }
  403. fmt.Printf("rotated %d oidc integrations\n", count)
  404. return nil
  405. }
  406. func rotateOAuthIntegrationModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  407. // get count of model
  408. var count int64
  409. if err := db.Model(&ints.OAuthIntegration{}).Count(&count).Error; err != nil {
  410. return err
  411. }
  412. // cluster-scoped repository
  413. repo := gorm.NewOAuthIntegrationRepository(db, oldKey).(*gorm.OAuthIntegrationRepository)
  414. // iterate (count / stepSize) + 1 times using Limit and Offset
  415. for i := 0; i < (int(count)/stepSize)+1; i++ {
  416. oauths := []*ints.OAuthIntegration{}
  417. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&oauths).Error; err != nil {
  418. return err
  419. }
  420. // decrypt with the old key
  421. for _, oauth := range oauths {
  422. err := repo.DecryptOAuthIntegrationData(oauth, oldKey)
  423. if err != nil {
  424. fmt.Printf("error decrypting oauth integration %d\n", oauth.ID)
  425. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  426. // recover it
  427. oauth.ClientID = []byte{}
  428. oauth.AccessToken = []byte{}
  429. oauth.RefreshToken = []byte{}
  430. }
  431. }
  432. // encrypt with the new key and re-insert
  433. for _, oauth := range oauths {
  434. err := repo.EncryptOAuthIntegrationData(oauth, newKey)
  435. if err != nil {
  436. fmt.Printf("error encrypting oauth integration %d\n", oauth.ID)
  437. return err
  438. }
  439. if err := db.Save(oauth).Error; err != nil {
  440. return err
  441. }
  442. }
  443. }
  444. fmt.Printf("rotated %d oauth integrations\n", count)
  445. return nil
  446. }
  447. func rotateGCPIntegrationModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  448. // get count of model
  449. var count int64
  450. if err := db.Model(&ints.GCPIntegration{}).Count(&count).Error; err != nil {
  451. return err
  452. }
  453. // cluster-scoped repository
  454. repo := gorm.NewGCPIntegrationRepository(db, oldKey).(*gorm.GCPIntegrationRepository)
  455. // iterate (count / stepSize) + 1 times using Limit and Offset
  456. for i := 0; i < (int(count)/stepSize)+1; i++ {
  457. gcps := []*ints.GCPIntegration{}
  458. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&gcps).Error; err != nil {
  459. return err
  460. }
  461. // decrypt with the old key
  462. for _, gcp := range gcps {
  463. err := repo.DecryptGCPIntegrationData(gcp, oldKey)
  464. if err != nil {
  465. fmt.Printf("error decrypting gcp integration %d\n", gcp.ID)
  466. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  467. // recover it
  468. gcp.GCPKeyData = []byte{}
  469. }
  470. }
  471. // encrypt with the new key and re-insert
  472. for _, gcp := range gcps {
  473. err := repo.EncryptGCPIntegrationData(gcp, newKey)
  474. if err != nil {
  475. fmt.Printf("error encrypting gcp integration %d\n", gcp.ID)
  476. return err
  477. }
  478. if err := db.Save(gcp).Error; err != nil {
  479. return err
  480. }
  481. }
  482. }
  483. fmt.Printf("rotated %d gcp integrations\n", count)
  484. return nil
  485. }
  486. func rotateAWSIntegrationModel(db *_gorm.DB, oldKey, newKey *[32]byte) error {
  487. // get count of model
  488. var count int64
  489. if err := db.Model(&ints.AWSIntegration{}).Count(&count).Error; err != nil {
  490. return err
  491. }
  492. // cluster-scoped repository
  493. repo := gorm.NewAWSIntegrationRepository(db, oldKey).(*gorm.AWSIntegrationRepository)
  494. // iterate (count / stepSize) + 1 times using Limit and Offset
  495. for i := 0; i < (int(count)/stepSize)+1; i++ {
  496. awss := []*ints.AWSIntegration{}
  497. if err := db.Order("id asc").Offset(i * stepSize).Limit(stepSize).Find(&awss).Error; err != nil {
  498. return err
  499. }
  500. // decrypt with the old key
  501. for _, aws := range awss {
  502. err := repo.DecryptAWSIntegrationData(aws, oldKey)
  503. if err != nil {
  504. fmt.Printf("error encrypting aws integration %d\n", aws.ID)
  505. // in these cases we'll wipe the data -- if it can't be decrypted, we can't
  506. // recover it
  507. aws.AWSAccessKeyID = []byte{}
  508. aws.AWSClusterID = []byte{}
  509. aws.AWSSecretAccessKey = []byte{}
  510. aws.AWSSessionToken = []byte{}
  511. }
  512. }
  513. // encrypt with the new key and re-insert
  514. for _, aws := range awss {
  515. err := repo.EncryptAWSIntegrationData(aws, newKey)
  516. if err != nil {
  517. fmt.Printf("error decrypting aws integration %d\n", aws.ID)
  518. return err
  519. }
  520. if err := db.Save(aws).Error; err != nil {
  521. return err
  522. }
  523. }
  524. }
  525. fmt.Printf("rotated %d aws integrations\n", count)
  526. return nil
  527. }