Guest User

Untitled

a guest
Dec 21st, 2018
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.17 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4. "bytes"
  5. "database/sql"
  6. "encoding/base64"
  7. "log"
  8. "os"
  9. "strings"
  10. "text/template"
  11.  
  12. _ "github.com/lib/pq"
  13. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  14. "k8s.io/client-go/kubernetes"
  15. "k8s.io/client-go/pkg/api/v1"
  16. "k8s.io/client-go/rest"
  17. )
  18.  
  19. // How to use this script:
  20. //
  21. // Create a deployment which depends on an RDS password and have a master RDS
  22. // password loaded as a secret.
  23. //
  24. // This script will given a version (v1):
  25. // 1. Create a new user with whatever role you'd like named `myuser_v1`.
  26. // 2. Create a secret `myapp-v1` with the password.
  27. // 3. Your app uses secret myapp-v1 and connects to the DB.
  28. //
  29. // Rolling the database password:
  30. // 1. Bump the version on this script to v2.
  31. // 2. Same user + new secret are created, your app is configured to use the v2
  32. // user.
  33. // 3. Importantly - now the old script will delete user v1 once no connections
  34. // are currently active with this username.
  35.  
  36. const createUser = `
  37. create role {{.User}} with password '{{.Password}}' login;
  38. grant {{.Role}} to {{.User}};
  39. `
  40.  
  41. func tpl(m map[string]string, tplStr string) (string, error) {
  42. t, err := template.New("").Parse(tplStr)
  43. if err != nil {
  44. return "", err
  45. }
  46.  
  47. buf := bytes.NewBuffer(nil)
  48. err = t.Execute(buf, m)
  49. if err != nil {
  50. return "", err
  51. }
  52. return buf.String(), nil
  53. }
  54.  
  55. func base64Enc(pass string) []byte {
  56. return []byte(base64.StdEncoding.EncodeToString([]byte(pass)))
  57. }
  58.  
  59. func main() {
  60. url := os.Getenv("DATABASE_URL")
  61. revision := os.Getenv("DATABASE_REVISION")
  62. user := os.Getenv("DATABASE_USER")
  63. password := os.Getenv("DATABASE_PASSWORD")
  64. role := os.Getenv("DATABASE_ROLE")
  65. namespace := os.Getenv("NAMESPACE")
  66. secret := os.Getenv("SECRET")
  67.  
  68. config, err := rest.InClusterConfig()
  69. if err != nil {
  70. log.Fatalf("failed to open k8s client: %v", err)
  71. }
  72.  
  73. clientset, err := kubernetes.NewForConfig(config)
  74. if err != nil {
  75. log.Fatalf("failed to open k8s client: %v", err)
  76. }
  77.  
  78. db, err := sql.Open("postgres", url)
  79. if err != nil {
  80. log.Fatalf("failed to open: %v", err)
  81. }
  82.  
  83. sql, err := tpl(map[string]string{
  84. "User": user + "_" + revision,
  85. "Password": password,
  86. "Role": role,
  87. }, createUser)
  88. if err != nil {
  89. log.Fatalf("failed to template: %v", err)
  90. }
  91.  
  92. // 1. Create a new user.
  93. _, err = db.Exec(sql)
  94. if err != nil {
  95. log.Fatalf("failed to exec: %v", err)
  96. }
  97.  
  98. // 2. Create a new secret for the given revision.
  99. _, err = clientset.CoreV1().Secrets(namespace).Create(&v1.Secret{
  100. ObjectMeta: metav1.ObjectMeta{
  101. Namespace: namespace,
  102. Name: secret + "-" + revision,
  103. },
  104. Data: map[string][]byte{
  105. "password": base64Enc(password),
  106. },
  107. })
  108. if err != nil {
  109. log.Fatalf("failed to create secret: %v", err)
  110. }
  111.  
  112. for {
  113. secrets, err := clientset.CoreV1().Secrets(namespace).List(metav1.ListOptions{})
  114. if err != nil {
  115. log.Fatalf("failed to list secrets: %v", err)
  116. }
  117.  
  118. for _, s := range secrets.Items {
  119. if strings.HasPrefix(s.ObjectMeta.Name, secret) &&
  120. s.ObjectMeta.Name != secret+"-"+revision {
  121.  
  122. currentRevSpl := strings.Split(s.ObjectMeta.Name, "-")
  123. currentRev := currentRevSpl[len(currentRevSpl)-1]
  124.  
  125. // Check if isn't currently used.
  126. db.Query("SELECT 1 from pg_stat_activity WHERE usename = ?", user+"_"+currentRev)
  127.  
  128. }
  129. }
  130. }
  131. }
Add Comment
Please, Sign In to add comment