@@ -20,8 +20,10 @@ import (
2020 "fmt"
2121 log "github.com/Sirupsen/logrus"
2222 _ "github.com/lib/pq"
23+ "strconv"
24+ "time"
2325 //"k8s.io/apimachinery/pkg/labels"
24- // "github.com/crunchydata/postgres-operator/operator/util"
26+ "github.com/crunchydata/postgres-operator/operator/util"
2527 //"github.com/crunchydata/postgres-operator/tpr"
2628 "github.com/spf13/cobra"
2729 //"github.com/spf13/viper"
@@ -32,35 +34,47 @@ import (
3234 //"strings"
3335)
3436
37+ type ConnInfo struct {
38+ Username string
39+ Hostip string
40+ StrPort string
41+ Database string
42+ Password string
43+ }
3544type PswResult struct {
3645 Rolname string
3746 Rolvaliduntil string
47+ ConnDetails ConnInfo
3848}
3949
50+ var Expired string
51+ var UpdatePasswords bool
52+
4053var pswCmd = & cobra.Command {
4154 Use : "psw" ,
4255 Short : "manage passwords" ,
4356 Long : `PSW allows you to manage passwords across a set of clusters
4457For example:
4558
4659pgo psw --selector=name=mycluster --update
47- pgo psw --dry-run --selector=someotherpolicy
60+ pgo psw --expired=7 --selector=someotherpolicy
4861.` ,
4962 Run : func (cmd * cobra.Command , args []string ) {
5063 log .Debug ("psw called" )
51- updatePasswords ()
64+ passwordManager ()
5265 },
5366}
5467
5568func init () {
5669 RootCmd .AddCommand (pswCmd )
5770
5871 pswCmd .Flags ().StringVarP (& Selector , "selector" , "s" , "" , "The selector to use for cluster filtering " )
59- pswCmd .Flags ().BoolVarP (& DryRun , "dry-run" , "d" , false , "--dry-run shows clusters and passwords that would be updated to but does not actually apply them" )
72+ pswCmd .Flags ().StringVarP (& Expired , "expired" , "e" , "" , "--expired=7 shows passwords that will expired in 7 days" )
73+ pswCmd .Flags ().BoolVarP (& UpdatePasswords , "update-passwords" , "u" , false , "--update-passwords performs password updating on expired passwords" )
6074
6175}
6276
63- func updatePasswords () {
77+ func passwordManager () {
6478 //build the selector based on the selector parameter
6579 //get the clusters list
6680
@@ -80,30 +94,31 @@ func updatePasswords() {
8094 return
8195 }
8296
83- if DryRun {
84- fmt .Println ("dry run only...." )
85- }
86-
8797 for _ , d := range deployments .Items {
88- fmt .Println ("deployment : " + d .ObjectMeta .Name )
89- getExpiredInfo (d .ObjectMeta .Name , "7" )
90- if ! DryRun {
98+ if Expired != "" {
99+ results := callDB (d .ObjectMeta .Name , Expired )
100+ if len (results ) > 0 {
101+ fmt .Println ("deployment : " + d .ObjectMeta .Name )
102+ fmt .Println ("expired passwords...." )
103+ for _ , v := range results {
104+ fmt .Printf ("RoleName %s Role Valid Until %s\n " , v .Rolname , v .Rolvaliduntil )
105+ if UpdatePasswords {
106+ newPassword := util .GeneratePassword (8 )
107+ newExpireDate := GeneratePasswordExpireDate (60 )
108+ err = updatePassword (v , newPassword , newExpireDate )
109+ if err != nil {
110+ fmt .Println ("error in updating password" )
111+ }
112+ fmt .Printf ("new password for %s is %s new expiration is %s\n " , v .Rolname , newPassword , newExpireDate )
113+ }
114+ }
115+ }
91116 }
92117
93118 }
94119
95120}
96121
97- func getExpiredInfo (clusterName , MAX_DAYS string ) {
98- //var err error
99-
100- results := callDB (clusterName , MAX_DAYS )
101- for _ , v := range results {
102- fmt .Printf ("RoleName %s Role Valid Until %s\n " , v .Rolname , v .Rolvaliduntil )
103- }
104-
105- }
106-
107122func callDB (clusterName , maxdays string ) []PswResult {
108123 var conn * sql.DB
109124
@@ -167,6 +182,9 @@ func callDB(clusterName, maxdays string) []PswResult {
167182
168183 for rows .Next () {
169184 p := PswResult {}
185+ c := ConnInfo {Username : username , Hostip : hostip , StrPort : strPort , Database : database , Password : password }
186+ p .ConnDetails = c
187+
170188 if err = rows .Scan (& p .Rolname , & p .Rolvaliduntil ); err != nil {
171189 log .Debug (err .Error ())
172190 return results
@@ -178,3 +196,53 @@ func callDB(clusterName, maxdays string) []PswResult {
178196 return results
179197
180198}
199+
200+ func updatePassword (p PswResult , newPassword , passwordExpireDate string ) error {
201+ var err error
202+ var conn * sql.DB
203+
204+ conn , err = sql .Open ("postgres" , "sslmode=disable user=" + p .ConnDetails .Username + " host=" + p .ConnDetails .Hostip + " port=" + p .ConnDetails .StrPort + " dbname=" + p .ConnDetails .Database + " password=" + p .ConnDetails .Password )
205+ if err != nil {
206+ log .Debug (err .Error ())
207+ return err
208+ }
209+
210+ //var ts string
211+ var rows * sql.Rows
212+
213+ querystr := "ALTER user " + p .Rolname + " PASSWORD '" + newPassword + "'"
214+ log .Debug (querystr )
215+ rows , err = conn .Query (querystr )
216+ if err != nil {
217+ log .Debug (err .Error ())
218+ return err
219+ }
220+ querystr = "ALTER user " + p .Rolname + " VALID UNTIL '" + passwordExpireDate + "'"
221+ log .Debug (querystr )
222+ rows , err = conn .Query (querystr )
223+ if err != nil {
224+ log .Debug (err .Error ())
225+ return err
226+ }
227+
228+ defer func () {
229+ if conn != nil {
230+ conn .Close ()
231+ }
232+ if rows != nil {
233+ rows .Close ()
234+ }
235+ }()
236+
237+ return err
238+ }
239+
240+ func GeneratePasswordExpireDate (daysFromNow int ) string {
241+
242+ now := time .Now ()
243+ totalHours := daysFromNow * 24
244+ diffDays , _ := time .ParseDuration (strconv .Itoa (totalHours ) + "h" )
245+ futureTime := now .Add (diffDays )
246+ return futureTime .Format ("2006-01-02" )
247+
248+ }
0 commit comments