Browse Source

Cleanup, redeploy, deal with expired certs

master
Chris Smith 5 years ago
parent
commit
ce833310ac
2 changed files with 73 additions and 26 deletions
  1. 49
    24
      dotege.go
  2. 24
    2
      lego.go

+ 49
- 24
dotege.go View File

31
 	return done
31
 	return done
32
 }
32
 }
33
 
33
 
34
-func main() {
34
+func createLogger() *zap.SugaredLogger {
35
 	zapConfig := zap.NewDevelopmentConfig()
35
 	zapConfig := zap.NewDevelopmentConfig()
36
 	zapConfig.DisableCaller = true
36
 	zapConfig.DisableCaller = true
37
 	zapConfig.DisableStacktrace = true
37
 	zapConfig.DisableStacktrace = true
39
 	zapConfig.OutputPaths = []string{"stdout"}
39
 	zapConfig.OutputPaths = []string{"stdout"}
40
 	zapConfig.ErrorOutputPaths = []string{"stdout"}
40
 	zapConfig.ErrorOutputPaths = []string{"stdout"}
41
 	logger, _ := zapConfig.Build()
41
 	logger, _ := zapConfig.Build()
42
-	sugar := logger.Sugar()
43
-	sugar.Info("Dotege is starting")
44
-
45
-	doneChan := monitorSignals()
42
+	return logger.Sugar()
43
+}
46
 
44
 
47
-	config := model.Config{
45
+func createConfig() *model.Config {
46
+	return &model.Config{
47
+		Templates: []model.TemplateConfig{
48
+			{
49
+				Source:      "./templates/haproxy.cfg.tpl",
50
+				Destination: "haproxy.cfg",
51
+			},
52
+		},
48
 		Labels: model.LabelConfig{
53
 		Labels: model.LabelConfig{
49
 			Hostnames:   "com.chameth.vhost",
54
 			Hostnames:   "com.chameth.vhost",
50
 			RequireAuth: "com.chameth.auth",
55
 			RequireAuth: "com.chameth.auth",
52
 		DefaultCertActions:     model.COMBINE | model.FLATTEN,
57
 		DefaultCertActions:     model.COMBINE | model.FLATTEN,
53
 		DefaultCertDestination: "/data/certs/",
58
 		DefaultCertDestination: "/data/certs/",
54
 	}
59
 	}
60
+}
55
 
61
 
56
-	dockerStopChan := make(chan struct{})
57
-	dockerClient, err := client.NewEnvClient()
62
+func createTemplateGenerator(logger *zap.SugaredLogger, config *model.Config) *TemplateGenerator {
63
+	templateGenerator := NewTemplateGenerator(logger)
64
+	for _, template := range config.Templates {
65
+		templateGenerator.AddTemplate(template)
66
+	}
67
+	return templateGenerator
68
+}
69
+
70
+func createCertificateManager(logger *zap.SugaredLogger) *CertificateManager {
71
+	certificateManager := NewCertificateManager(logger, lego.LEDirectoryStaging, certcrypto.EC256, env.GetOrDefaultString("DOTEGE_DNS_PROVIDER", ""), "/config/certs.json")
72
+	err := certificateManager.Init(env.GetOrDefaultString("DOTEGE_ACME_EMAIL", ""))
58
 	if err != nil {
73
 	if err != nil {
59
 		panic(err)
74
 		panic(err)
60
 	}
75
 	}
76
+	return certificateManager
77
+}
61
 
78
 
62
-	templateGenerator := NewTemplateGenerator(sugar)
63
-	templateGenerator.AddTemplate(model.TemplateConfig{
64
-		Source:      "./templates/haproxy.cfg.tpl",
65
-		Destination: "haproxy.cfg",
66
-	})
79
+func main() {
80
+	logger := createLogger()
81
+	logger.Info("Dotege is starting")
82
+
83
+	doneChan := monitorSignals()
84
+	config := createConfig()
67
 
85
 
68
-	certificateManager := NewCertificateManager(sugar, lego.LEDirectoryStaging, certcrypto.EC256, env.GetOrDefaultString("DOTEGE_DNS_PROVIDER", ""), "/config/certs.json")
69
-	err = certificateManager.Init(env.GetOrDefaultString("DOTEGE_ACME_EMAIL", ""))
86
+	dockerStopChan := make(chan struct{})
87
+	dockerClient, err := client.NewEnvClient()
70
 	if err != nil {
88
 	if err != nil {
71
 		panic(err)
89
 		panic(err)
72
 	}
90
 	}
73
 
91
 
74
-	timer := time.NewTimer(time.Hour)
75
-	timer.Stop()
92
+	templateGenerator := createTemplateGenerator(logger, config)
93
+	certificateManager := createCertificateManager(logger)
94
+
95
+	jitterTimer := time.NewTimer(time.Minute)
96
+	redeployTimer := time.NewTicker(time.Hour * 24)
76
 	containers := make(map[string]model.Container)
97
 	containers := make(map[string]model.Container)
77
 
98
 
78
 	go func() {
99
 	go func() {
79
 		err := monitorContainers(dockerClient, dockerStopChan, func(container model.Container) {
100
 		err := monitorContainers(dockerClient, dockerStopChan, func(container model.Container) {
80
 			containers[container.Name] = container
101
 			containers[container.Name] = container
81
-			timer.Reset(100 * time.Millisecond)
82
-			err, _ = certificateManager.GetCertificate(getHostnamesForContainer(container, config))
102
+			jitterTimer.Reset(100 * time.Millisecond)
103
+			err, _ = certificateManager.GetCertificate(getHostnamesForContainer(container, *config))
83
 		}, func(name string) {
104
 		}, func(name string) {
84
 			delete(containers, name)
105
 			delete(containers, name)
85
-			timer.Reset(100 * time.Millisecond)
106
+			jitterTimer.Reset(100 * time.Millisecond)
86
 		})
107
 		})
87
 
108
 
88
 		if err != nil {
109
 		if err != nil {
89
-			sugar.Fatal("Error monitoring containers: ", err.Error())
110
+			logger.Fatal("Error monitoring containers: ", err.Error())
90
 		}
111
 		}
91
 	}()
112
 	}()
92
 
113
 
93
 	go func() {
114
 	go func() {
94
 		for {
115
 		for {
95
 			select {
116
 			select {
96
-			case <-timer.C:
97
-				hostnames := getHostnames(containers, config)
117
+			case <-jitterTimer.C:
118
+				hostnames := getHostnames(containers, *config)
98
 				templateGenerator.Generate(Context{
119
 				templateGenerator.Generate(Context{
99
 					Containers: containers,
120
 					Containers: containers,
100
 					Hostnames:  hostnames,
121
 					Hostnames:  hostnames,
101
 				})
122
 				})
102
-				//certDeployer.UpdateHostnames(hostnames)
123
+			case <-redeployTimer.C:
124
+				logger.Info("Performing periodic certificate refresh")
125
+				for _, container := range containers {
126
+					err, _ = certificateManager.GetCertificate(getHostnamesForContainer(container, *config))
127
+				}
103
 			}
128
 			}
104
 		}
129
 		}
105
 	}()
130
 	}()

+ 24
- 2
lego.go View File

184
 func (c *CertificateManager) GetCertificate(domains []string) (error, *SavedCertificate) {
184
 func (c *CertificateManager) GetCertificate(domains []string) (error, *SavedCertificate) {
185
 	existing := c.loadCert(domains)
185
 	existing := c.loadCert(domains)
186
 	if existing != nil {
186
 	if existing != nil {
187
-		c.logger.Debugf("Returning existing certificate for request %s", domains)
188
-		return nil, existing
187
+		if existing.NotAfter.Before(time.Now().Add(time.Hour * 24 * 31)) {
188
+			c.logger.Debugf("Found existing certificate for %s, but it expires soon; renewing", domains)
189
+		} else {
190
+			c.logger.Debugf("Returning existing certificate for request %s", domains)
191
+			return nil, existing
192
+		}
189
 	}
193
 	}
190
 
194
 
191
 	request := certificate.ObtainRequest{
195
 	request := certificate.ObtainRequest{
226
 	return true
230
 	return true
227
 }
231
 }
228
 
232
 
233
+func (c *CertificateManager) removeCerts(domains []string) {
234
+	var newCerts []*SavedCertificate
235
+	for _, cert := range c.data.Certs {
236
+		if !domainsMatch(cert.Domains, domains) {
237
+			newCerts = append(newCerts, cert)
238
+		}
239
+	}
240
+
241
+	diff := len(c.data.Certs) - len(newCerts)
242
+
243
+	if diff > 0 {
244
+		c.logger.Debugf("Removed %d certificates matching %s", diff, domains)
245
+		c.data.Certs = newCerts
246
+	}
247
+}
248
+
229
 func (c *CertificateManager) saveCert(domains []string, cert *certificate.Resource) (error, *SavedCertificate) {
249
 func (c *CertificateManager) saveCert(domains []string, cert *certificate.Resource) (error, *SavedCertificate) {
250
+	c.removeCerts(domains)
251
+
230
 	savedCert := &SavedCertificate{
252
 	savedCert := &SavedCertificate{
231
 		Domains:           domains,
253
 		Domains:           domains,
232
 		Certificate:       cert.Certificate,
254
 		Certificate:       cert.Certificate,

Loading…
Cancel
Save