Browse Source

Skeleton certificate scanning

Fix bug in hostname generation not adding additional containers
master
Chris Smith 5 years ago
parent
commit
4b014b272b
4 changed files with 102 additions and 8 deletions
  1. 0
    1
      certificate_manager.go
  2. 91
    0
      certs/certificate_manager.go
  3. 9
    4
      dotege.go
  4. 2
    3
      template_generator.go

+ 0
- 1
certificate_manager.go View File

1
-package main

+ 91
- 0
certs/certificate_manager.go View File

1
+package certs
2
+
3
+import (
4
+	"go.uber.org/zap"
5
+	"io/ioutil"
6
+	"path"
7
+	"strings"
8
+	"time"
9
+)
10
+
11
+// CertificateManager handles scanning for new/updated certificates and deploying them to a destination.
12
+type CertificateManager struct {
13
+	logger      *zap.SugaredLogger
14
+	directories []string
15
+}
16
+
17
+type foundCertificate struct {
18
+	cert       string
19
+	chain      string
20
+	fullChain  string
21
+	privateKey string
22
+	modTime    time.Time
23
+}
24
+
25
+// NewCertificateManager creates a new CertificateManager.
26
+func NewCertificateManager(logger *zap.SugaredLogger) *CertificateManager {
27
+	return &CertificateManager{
28
+		logger: logger,
29
+	}
30
+}
31
+
32
+func (c *CertificateManager) AddDirectory(directory string) {
33
+	c.directories = append(c.directories, directory)
34
+	go c.scanForFolders(directory)
35
+}
36
+
37
+func (c *CertificateManager) scanForFolders(dir string) {
38
+	dirs, err := ioutil.ReadDir(dir)
39
+	if err != nil {
40
+		c.logger.Errorf("Unable to read directory %s - %s", dir, err.Error())
41
+		return
42
+	}
43
+
44
+	for _, d := range dirs {
45
+		if d.IsDir() {
46
+			c.scanForCerts(d.Name(), path.Join(dir, d.Name()))
47
+		}
48
+	}
49
+}
50
+
51
+func (c *CertificateManager) scanForCerts(vhost string, dir string) {
52
+	files, err := ioutil.ReadDir(dir)
53
+	if err != nil {
54
+		c.logger.Errorf("Unable to read directory %s - %s", dir, err.Error())
55
+		return
56
+	}
57
+
58
+	cert := foundCertificate{}
59
+	for _, f := range files {
60
+		ext := path.Ext(f.Name())
61
+		base := path.Base(f.Name())
62
+		if ext == "" && strings.Contains(base, "-") {
63
+			switch parts := strings.Split(base, "-"); parts[0] {
64
+			case "cert":
65
+				cert.cert = path.Join(dir, f.Name())
66
+				if f.ModTime().After(cert.modTime) {
67
+					cert.modTime = f.ModTime()
68
+				}
69
+			case "chain":
70
+				cert.chain = path.Join(dir, f.Name())
71
+				if f.ModTime().After(cert.modTime) {
72
+					cert.modTime = f.ModTime()
73
+				}
74
+			case "fullchain":
75
+				cert.fullChain = path.Join(dir, f.Name())
76
+				if f.ModTime().After(cert.modTime) {
77
+					cert.modTime = f.ModTime()
78
+				}
79
+			case "privkey":
80
+				cert.privateKey = path.Join(dir, f.Name())
81
+				if f.ModTime().After(cert.modTime) {
82
+					cert.modTime = f.ModTime()
83
+				}
84
+			}
85
+		}
86
+	}
87
+
88
+	if len(cert.cert) > 0 && len(cert.chain) > 0 && len(cert.fullChain) > 0 && len(cert.privateKey) > 0 {
89
+		c.logger.Debugf("Found certificate files for %s in %s", vhost, dir)
90
+	}
91
+}

+ 9
- 4
dotege.go View File

2
 
2
 
3
 import (
3
 import (
4
 	"fmt"
4
 	"fmt"
5
+	"github.com/csmith/dotege/certs"
5
 	"github.com/csmith/dotege/docker"
6
 	"github.com/csmith/dotege/docker"
6
 	"github.com/csmith/dotege/model"
7
 	"github.com/csmith/dotege/model"
7
 	"github.com/docker/docker/client"
8
 	"github.com/docker/docker/client"
32
 func main() {
33
 func main() {
33
 	config := zap.NewDevelopmentConfig()
34
 	config := zap.NewDevelopmentConfig()
34
 	config.DisableCaller = true
35
 	config.DisableCaller = true
36
+	config.DisableStacktrace = true
35
 	config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
37
 	config.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
36
 	config.OutputPaths = []string{"stdout"}
38
 	config.OutputPaths = []string{"stdout"}
37
 	config.ErrorOutputPaths = []string{"stdout"}
39
 	config.ErrorOutputPaths = []string{"stdout"}
51
 		panic(err)
53
 		panic(err)
52
 	}
54
 	}
53
 
55
 
56
+	certMonitor := certs.NewCertificateManager(sugar)
57
+	certMonitor.AddDirectory("/certs/certs")
58
+
54
 	templateGenerator := NewTemplateGenerator(sugar)
59
 	templateGenerator := NewTemplateGenerator(sugar)
55
 	templateGenerator.AddTemplate(model.TemplateConfig{
60
 	templateGenerator.AddTemplate(model.TemplateConfig{
56
 		Source:      "./templates/domains.txt.tpl",
61
 		Source:      "./templates/domains.txt.tpl",
94
 	}
99
 	}
95
 }
100
 }
96
 
101
 
97
-func getHostnames(containers map[string]model.Container, config model.LabelConfig) (hostnames map[string]model.Hostname) {
98
-	hostnames = make(map[string]model.Hostname)
102
+func getHostnames(containers map[string]model.Container, config model.LabelConfig) (hostnames map[string]*model.Hostname) {
103
+	hostnames = make(map[string]*model.Hostname)
99
 	for _, container := range containers {
104
 	for _, container := range containers {
100
 		if label, ok := container.Labels[config.Hostnames]; ok {
105
 		if label, ok := container.Labels[config.Hostnames]; ok {
101
 			names := strings.Split(strings.Replace(label, ",", " ", -1), " ")
106
 			names := strings.Split(strings.Replace(label, ",", " ", -1), " ")
102
 			if hostname, ok := hostnames[names[0]]; ok {
107
 			if hostname, ok := hostnames[names[0]]; ok {
103
 				hostname.Containers = append(hostname.Containers, container)
108
 				hostname.Containers = append(hostname.Containers, container)
104
 			} else {
109
 			} else {
105
-				hostnames[names[0]] = model.Hostname{
110
+				hostnames[names[0]] = &model.Hostname{
106
 					Name:         names[0],
111
 					Name:         names[0],
107
 					Alternatives: make(map[string]bool),
112
 					Alternatives: make(map[string]bool),
108
 					Containers:   []model.Container{container},
113
 					Containers:   []model.Container{container},
114
 	return
119
 	return
115
 }
120
 }
116
 
121
 
117
-func addAlternatives(hostname model.Hostname, alternatives []string) {
122
+func addAlternatives(hostname *model.Hostname, alternatives []string) {
118
 	for _, alternative := range alternatives {
123
 	for _, alternative := range alternatives {
119
 		hostname.Alternatives[alternative] = true
124
 		hostname.Alternatives[alternative] = true
120
 	}
125
 	}

+ 2
- 3
template_generator.go View File

12
 
12
 
13
 type Context struct {
13
 type Context struct {
14
 	Containers map[string]model.Container
14
 	Containers map[string]model.Container
15
-	Hostnames  map[string]model.Hostname
15
+	Hostnames  map[string]*model.Hostname
16
 }
16
 }
17
 
17
 
18
 type Template struct {
18
 type Template struct {
67
 			panic(err)
67
 			panic(err)
68
 		}
68
 		}
69
 		if tmpl.content != builder.String() {
69
 		if tmpl.content != builder.String() {
70
-			t.logger.Debugf("%s has been updated, writing to %s", tmpl.config.Source, tmpl.config.Destination)
71
-			t.logger.Debug(builder.String())
70
+			t.logger.Infof("Writing updated template to %s", tmpl.config.Destination)
72
 			tmpl.content = builder.String()
71
 			tmpl.content = builder.String()
73
 			err = ioutil.WriteFile(tmpl.config.Destination, []byte(builder.String()), 0666)
72
 			err = ioutil.WriteFile(tmpl.config.Destination, []byte(builder.String()), 0666)
74
 			if err != nil {
73
 			if err != nil {

Loading…
Cancel
Save