@@ -36,6 +36,8 @@ import (
3636 log "github.com/sirupsen/logrus"
3737)
3838
39+ const DataplaneAPIType = "community"
40+
3941//Node is structure required for connection to cluster
4042type Node struct {
4143 Address string `json:"address"`
@@ -64,6 +66,9 @@ func (c *ClusterSync) Monitor(cfg *Configuration, cli *client_native.HAProxyClie
6466 c .cli = cli
6567
6668 go c .monitorBootstrapKey ()
69+ if c .cfg .Mode .Load () == "cluster" {
70+ go c .monitorCertificateRefresh ()
71+ }
6772
6873 c .certFetch = make (chan struct {}, 2 )
6974 go c .fetchCert ()
@@ -76,6 +81,98 @@ func (c *ClusterSync) Monitor(cfg *Configuration, cli *client_native.HAProxyClie
7681 }
7782}
7883
84+ func (c * ClusterSync ) monitorCertificateRefresh () {
85+ for range c .cfg .Notify .CertificateRefresh .Subscribe ("monitorCertificateRefresh" ) {
86+ log .Info ("refreshing certificate" )
87+
88+ key := c .cfg .BootstrapKey .Load ()
89+ data , err := decodeBootstrapKey (key )
90+ if err != nil {
91+ log .Warning (err )
92+ continue
93+ }
94+ if len (data ) != 8 {
95+ log .Warning ("bottstrap key in unrecognized format" )
96+ continue
97+ }
98+ url := fmt .Sprintf ("%s://%s" , data [0 ], data [1 ])
99+
100+ csr , key , err := generateCSR ()
101+ if err != nil {
102+ log .Warning (err )
103+ continue
104+ }
105+ err = ioutil .WriteFile (c .cfg .Cluster .CertificateCSR .Load (), []byte (csr ), 0644 )
106+ if err != nil {
107+ log .Warning (err )
108+ continue
109+ }
110+ err = c .issueRefreshRequest (url , data [2 ], data [3 ], data [4 ], csr , key )
111+ if err != nil {
112+ log .Warning (err )
113+ continue
114+ }
115+ }
116+ }
117+
118+ func (c * ClusterSync ) issueRefreshRequest (url , port , basePath string , nodesPath string , csr , key string ) error {
119+ url = fmt .Sprintf ("%s:%s%s/%s/%s" , url , port , basePath , nodesPath , c .cfg .Cluster .ID .Load ())
120+ nodeData := Node {
121+ ID : c .cfg .Cluster .ID .Load (),
122+ Address : c .cfg .Server .Host ,
123+ Certificate : csr ,
124+ Status : cfg .Status .Load (),
125+ Type : DataplaneAPIType ,
126+ }
127+ bytesRepresentation , _ := json .Marshal (nodeData )
128+
129+ req , err := http .NewRequest ("PATCH" , url , bytes .NewBuffer (bytesRepresentation ))
130+ if err != nil {
131+ return fmt .Errorf ("error creating new POST request for cluster comunication" )
132+ }
133+ req .Header .Add ("X-Node-Key" , c .cfg .Cluster .Token .Load ())
134+ req .Header .Add ("Content-Type" , "application/json" )
135+ log .Infof ("Refreshing certificate %s" , url )
136+ httpClient := createHTTPClient ()
137+ resp , err := httpClient .Do (req )
138+ if err != nil {
139+ return err
140+ }
141+ defer resp .Body .Close ()
142+
143+ body , err := ioutil .ReadAll (resp .Body )
144+ if err != nil {
145+ return err
146+ }
147+ if resp .StatusCode != 202 {
148+ return fmt .Errorf ("status code not proper [%d] %s" , resp .StatusCode , string (body ))
149+ }
150+ var responseData Node
151+ err = json .Unmarshal (body , & responseData )
152+ if err != nil {
153+ return err
154+ }
155+ log .Infof ("Cluster re joined, status: %s" , responseData .Status )
156+ err = ioutil .WriteFile (c .cfg .Cluster .CertificatePath .Load (), []byte (responseData .Certificate ), 0644 )
157+ if err != nil {
158+ log .Warning (err )
159+ return err
160+ }
161+ err = ioutil .WriteFile (c .cfg .Cluster .CertificateKeyPath .Load (), []byte (key ), 0644 )
162+ if err != nil {
163+ log .Warning (err )
164+ return err
165+ }
166+ c .cfg .Cluster .Token .Store (resp .Header .Get ("X-Node-Key" ))
167+ err = c .cfg .Save ()
168+ if err != nil {
169+ log .Warning (err )
170+ return err
171+ }
172+ c .cfg .Notify .Reload .Notify ()
173+ return nil
174+ }
175+
79176func (c * ClusterSync ) monitorBootstrapKey () {
80177 for range c .cfg .Notify .BootstrapKeyChanged .Subscribe ("monitorBootstrapKey" ) {
81178 key := c .cfg .BootstrapKey .Load ()
@@ -173,7 +270,7 @@ func (c *ClusterSync) issueJoinRequest(url, port, basePath string, nodesPath str
173270 Name : c .cfg .Name .Load (),
174271 Port : int64 (serverCfg .Port ),
175272 Status : "waiting_approval" ,
176- Type : "community" ,
273+ Type : DataplaneAPIType ,
177274 }
178275 bytesRepresentation , _ := json .Marshal (nodeData )
179276
0 commit comments