Skip to content

Commit fc6b183

Browse files
committed
FEATURE/MINOR: cluster: allow defining path to store certificates
cli argument for passing directory to store certificates is 'cluster-tls-dir'
1 parent a285673 commit fc6b183

File tree

3 files changed

+40
-29
lines changed

3 files changed

+40
-29
lines changed

cmd/dataplaneapi/main.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package main
1818
import (
1919
"fmt"
2020
"os"
21+
"path"
2122

2223
log "github.com/sirupsen/logrus"
2324

@@ -125,10 +126,10 @@ func startServer(cfg *configuration.Configuration) (reload configuration.AtomicB
125126
log.Infof("Build date: %s", BuildTime)
126127

127128
if cfg.Mode.Load() == "cluster" {
128-
if cfg.Cluster.CertFetched.Load() {
129+
if cfg.Cluster.Certificate.Fetched.Load() {
129130
log.Info("HAProxy Data Plane API in cluster mode")
130-
server.TLSCertificate = flags.Filename(cfg.Cluster.CertificatePath.Load())
131-
server.TLSCertificateKey = flags.Filename(cfg.Cluster.CertificateKeyPath.Load())
131+
server.TLSCertificate = flags.Filename(path.Join(cfg.GetClusterCertDir(), fmt.Sprintf("dataplane-%s.crt", cfg.Name.Load())))
132+
server.TLSCertificateKey = flags.Filename(path.Join(cfg.GetClusterCertDir(), fmt.Sprintf("dataplane-%s.key", cfg.Name.Load())))
132133
server.EnabledListeners = []string{"https"}
133134
if server.TLSPort == 0 {
134135
server.TLSPort = server.Port

configuration/cluster_sync.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ import (
2828
"fmt"
2929
"io/ioutil"
3030
"net/http"
31+
"path"
3132
"strings"
3233
"time"
3334

35+
"github.com/google/renameio"
3436
client_native "github.com/haproxytech/client-native/v2"
3537
"github.com/haproxytech/config-parser/v2/types"
3638
"github.com/haproxytech/dataplaneapi/haproxy"
@@ -75,7 +77,7 @@ func (c *ClusterSync) Monitor(cfg *Configuration, cli *client_native.HAProxyClie
7577
go c.fetchCert()
7678

7779
key := c.cfg.BootstrapKey.Load()
78-
certFetched := cfg.Cluster.CertFetched.Load()
80+
certFetched := cfg.Cluster.Certificate.Fetched.Load()
7981

8082
if key != "" && !certFetched {
8183
c.cfg.Notify.BootstrapKeyChanged.Notify()
@@ -99,7 +101,7 @@ func (c *ClusterSync) monitorCertificateRefresh() {
99101
log.Warning(err)
100102
continue
101103
}
102-
err = ioutil.WriteFile(c.cfg.Cluster.CertificateCSR.Load(), []byte(csr), 0644)
104+
err = renameio.WriteFile(path.Join(c.cfg.GetClusterCertDir(), fmt.Sprintf("dataplane-%s-csr.crt", c.cfg.Name.Load())), []byte(csr), 0644)
103105
if err != nil {
104106
log.Warning(err)
105107
continue
@@ -154,12 +156,12 @@ func (c *ClusterSync) issueRefreshRequest(url, port, basePath string, nodesPath
154156
return err
155157
}
156158
log.Infof("Cluster re joined, status: %s", responseData.Status)
157-
err = ioutil.WriteFile(c.cfg.Cluster.CertificatePath.Load(), []byte(responseData.Certificate), 0644)
159+
err = renameio.WriteFile(path.Join(c.cfg.GetClusterCertDir(), fmt.Sprintf("dataplane-%s.crt", c.cfg.Name.Load())), []byte(csr), 0644)
158160
if err != nil {
159161
log.Warning(err)
160162
return err
161163
}
162-
err = ioutil.WriteFile(c.cfg.Cluster.CertificateKeyPath.Load(), []byte(key), 0644)
164+
err = renameio.WriteFile(path.Join(c.cfg.GetClusterCertDir(), fmt.Sprintf("dataplane-%s.key", c.cfg.Name.Load())), []byte(key), 0644)
163165
if err != nil {
164166
log.Warning(err)
165167
return err
@@ -177,7 +179,7 @@ func (c *ClusterSync) issueRefreshRequest(url, port, basePath string, nodesPath
177179
func (c *ClusterSync) monitorBootstrapKey() {
178180
for range c.cfg.Notify.BootstrapKeyChanged.Subscribe("monitorBootstrapKey") {
179181
key := c.cfg.BootstrapKey.Load()
180-
c.cfg.Cluster.CertFetched.Store(false)
182+
c.cfg.Cluster.Certificate.Fetched.Store(false)
181183
if key == "" {
182184
//do we need to delete cert here maybe?
183185
c.cfg.Cluster.ActiveBootstrapKey.Store("")
@@ -188,7 +190,7 @@ func (c *ClusterSync) monitorBootstrapKey() {
188190
continue
189191
}
190192
if key == c.cfg.Cluster.ActiveBootstrapKey.Load() {
191-
fetched := c.cfg.Cluster.CertFetched.Load()
193+
fetched := c.cfg.Cluster.Certificate.Fetched.Load()
192194
if !fetched {
193195
c.certFetch <- struct{}{}
194196
}
@@ -215,12 +217,12 @@ func (c *ClusterSync) monitorBootstrapKey() {
215217
log.Warning(err)
216218
continue
217219
}
218-
err = ioutil.WriteFile(c.cfg.Cluster.CertificateKeyPath.Load(), []byte(key), 0644)
220+
err = renameio.WriteFile(path.Join(c.cfg.GetClusterCertDir(), fmt.Sprintf("dataplane-%s.key", c.cfg.Name.Load())), []byte(key), 0644)
219221
if err != nil {
220222
log.Warning(err)
221223
continue
222224
}
223-
err = ioutil.WriteFile(c.cfg.Cluster.CertificateCSR.Load(), []byte(csr), 0644)
225+
err = renameio.WriteFile(path.Join(c.cfg.GetClusterCertDir(), fmt.Sprintf("dataplane-%s-csr.crt", c.cfg.Name.Load())), []byte(csr), 0644)
224226
if err != nil {
225227
log.Warning(err)
226228
continue
@@ -388,12 +390,12 @@ func (c *ClusterSync) checkCertificate(node Node) (fetched bool, err error) {
388390
c.cfg.Status.Store("unconfigured")
389391
return false, nil
390392
}
391-
err = ioutil.WriteFile(c.cfg.Cluster.CertificatePath.Load(), []byte(node.Certificate), 0644)
393+
err = renameio.WriteFile(path.Join(c.cfg.GetClusterCertDir(), fmt.Sprintf("dataplane-%s.crt", c.cfg.Name.Load())), []byte(node.Certificate), 0644)
392394
if err != nil {
393395
c.cfg.Status.Store("unconfigured")
394396
return false, err
395397
}
396-
c.cfg.Cluster.CertFetched.Store(true)
398+
c.cfg.Cluster.Certificate.Fetched.Store(true)
397399
c.cfg.Notify.Reload.Notify()
398400
c.cfg.Status.Store("active")
399401
return true, nil
@@ -414,7 +416,7 @@ func (c *ClusterSync) fetchCert() {
414416
continue
415417
}
416418
//if not, sleep and start all over again
417-
certFetched := c.cfg.Cluster.CertFetched.Load()
419+
certFetched := c.cfg.Cluster.Certificate.Fetched.Load()
418420
if !certFetched {
419421
url := c.cfg.Cluster.URL.Load()
420422
port := c.cfg.Cluster.Port.Load()

configuration/configuration.go

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ package configuration
1818
import (
1919
"encoding/json"
2020
"io/ioutil"
21+
"path/filepath"
2122

2223
"math/rand"
2324
"time"
2425

26+
"github.com/google/renameio"
2527
log "github.com/sirupsen/logrus"
2628

2729
petname "github.com/dustinkirkland/golang-petname"
@@ -48,6 +50,7 @@ type HAProxyConfiguration struct {
4850
MapsDir string `short:"p" long:"maps-dir" description:"Path to maps directory. If set, it reads from specified dir, otherwise it reads from config file"`
4951
UpdateMapFiles bool `long:"update-map-files" description:"Flag used for syncing map files with runtime maps values"`
5052
UpdateMapFilesPeriod int64 `long:"update-map-files-period" description:"Elapsed time in seconds between two maps syncing operations" default:"10"`
53+
ClusterTLSCertDir string `long:"cluster-tls-dir" description:"Path where cluster tls certificates will be stored. Defaults to same directory as dataplane configuration file"`
5154
}
5255

5356
type APIConfiguration struct {
@@ -70,13 +73,14 @@ type ClusterConfiguration struct {
7073
Port AtomicString `yaml:"port"`
7174
APIBasePath AtomicString `yaml:"api_base_path"`
7275
APINodesPath AtomicString `yaml:"api_nodes_path"`
73-
CertificatePath AtomicString `yaml:"tls_certificate"`
74-
CertificateKeyPath AtomicString `yaml:"tls_key"`
75-
CertificateCSR AtomicString `yaml:"tls_csr"`
76-
CertFetched AtomicBool `yaml:"cert_fetched"`
76+
Certificate ClusterTLS `yaml:"certificates"`
7777
Name AtomicString `yaml:"name"`
7878
Description AtomicString `yaml:"description"`
7979
}
80+
type ClusterTLS struct {
81+
Dir AtomicString `yaml:"path"`
82+
Fetched AtomicBool `yaml:"fetched"`
83+
}
8084

8185
func (c *ClusterConfiguration) Clear() {
8286
c.ID.Store("")
@@ -85,7 +89,7 @@ func (c *ClusterConfiguration) Clear() {
8589
c.Port.Store("")
8690
c.APIBasePath.Store("")
8791
c.APINodesPath.Store("")
88-
c.CertFetched.Store(false)
92+
c.Certificate.Fetched.Store(false)
8993
c.Name.Store("")
9094
c.Description.Store("")
9195
}
@@ -177,15 +181,6 @@ func (c *Configuration) Load(swaggerJSON json.RawMessage, host string, port int)
177181
if c.Mode.Load() == "" {
178182
c.Mode.Store("single")
179183
}
180-
if c.Cluster.CertificatePath.Load() == "" {
181-
c.Cluster.CertificatePath.Store("tls.crt")
182-
}
183-
if c.Cluster.CertificateKeyPath.Load() == "" {
184-
c.Cluster.CertificateKeyPath.Store("tls.key")
185-
}
186-
if c.Cluster.CertificateCSR.Load() == "" {
187-
c.Cluster.CertificateCSR.Store("csr.crt")
188-
}
189184

190185
if c.Name.Load() == "" {
191186
rand.Seed(time.Now().UnixNano())
@@ -205,9 +200,22 @@ func (c *Configuration) Save() error {
205200
log.Fatalf("error: %v", err)
206201
}
207202

208-
err = ioutil.WriteFile(c.HAProxy.DataplaneConfig, data, 0644)
203+
err = renameio.WriteFile(c.HAProxy.DataplaneConfig, data, 0644)
209204
if err != nil {
210205
return err
211206
}
212207
return nil
213208
}
209+
210+
func (c *Configuration) GetClusterCertDir() string {
211+
dir := c.Cluster.Certificate.Dir.Load()
212+
if dir == "" {
213+
dir = c.HAProxy.ClusterTLSCertDir
214+
}
215+
if dir == "" {
216+
// use same dir as dataplane config file
217+
url := c.HAProxy.DataplaneConfig
218+
dir = filepath.Dir(url)
219+
}
220+
return dir
221+
}

0 commit comments

Comments
 (0)