-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtypes.go
195 lines (159 loc) · 4.52 KB
/
types.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package main
import (
"encoding/json"
"github.com/aws/aws-sdk-go/aws/session"
"go.uber.org/zap"
"strings"
"sync"
"time"
)
// Config holds processed configuration from environment variables
type Config struct {
ConfigDir string `default:"/etc/ssl-watch" split_words:"true"`
ConfigFileSuffix string `default:".conf" split_words:"true"`
ScrapeInterval time.Duration `default:"60s" split_words:"true"`
ConnectionTimeout time.Duration `default:"10s" split_words:"true"`
LookupTimeout time.Duration `default:"5s" split_words:"true"`
ConfigCheckInterval time.Duration `default:"5m" split_words:"true"`
DebugMode bool `default:"false" split_words:"true"`
Port string `default:"9105"`
AutoReload bool `default:"true" split_words:"true"`
S3Region string `default:"us-east-1" split_words:"true"`
S3Bucket string
S3Key string
}
// Endpoint is a struct for holding info about a single domain endpoint,
// i.e. IP address. If we can't connect to this endpoint, we set alive
// to false.
type Endpoint struct {
CN string
AltNamesCount int
sha256 string
expiry time.Time
valid bool
alive bool
}
// Endpoints is a map of domains to endpoints.
type Endpoints map[string]Endpoint
// Metrics is basically just a wrapper around Endpoints + mutex.
type Metrics struct {
db map[string]Endpoints
mutex sync.RWMutex
}
// Service is a struct for a user defined service, which is
// an arbitrary service name, a list of domains with
// optional IP endpoints, and an optional list of named IP sets:
// ---JSON---
// { "serviceName" :
// "ips" : { "set1" : [ "127.0.0.1", "127.0.0.2", "127.0.0.3" ], "set2": [ "127.0.0.4" ] },
// "domains" : { "example.com": [], "sample.net": [ "set1", "set2", "127.0.0.5" ] }
// }
// ---JSON---
type Service struct {
Desc string `json:"desc,omitempty"`
Domains map[string][]string `json:"domains"`
IPs map[string][]string `json:"ips,omitempty"`
}
// Services is a wrapper over a map of services with mutex.
// It also includes reverseMap to ease looking up service name
// by domain.
type Services struct {
db map[string]Service
reverseMap map[string]string
mutex sync.RWMutex
}
// App is main struct of ssl-watch that,
// after initialization, holds instances of
// Config, Metrics and Domains structures +
// a logger interface.
type App struct {
config Config
services Services
log zap.Logger
metrics Metrics
S3Configs map[string]string
S3Session *session.Session
}
func (s *Services) Flush() {
s.mutex.Lock()
s.db = map[string]Service{}
s.reverseMap = map[string]string{}
s.mutex.Unlock()
}
func (s *Services) Update(rawJSON []byte) {
defer s.mutex.Unlock()
s.mutex.Lock()
_ = json.Unmarshal(rawJSON, &s.db)
for name, service := range s.db {
for domain := range service.Domains {
s.reverseMap[domain] = name
}
}
}
func (s *Services) ListDomains() []string {
defer s.mutex.RUnlock()
s.mutex.RLock()
domains := []string{}
for domain := range s.reverseMap {
domains = append(domains, domain)
}
return domains
}
func (s *Services) GetIPs(domain string) []string {
serviceName, exists := s.GetServiceName(domain)
ips := []string{}
if exists {
s.mutex.RLock()
service, exists := s.db[serviceName]
if exists {
for _, ip := range service.Domains[domain] {
if !strings.Contains(ip, ".") {
ips = append(ips, service.IPs[ip]...)
} else {
ips = append(ips, ip)
}
}
}
s.mutex.RUnlock()
}
return ips
}
func (s *Services) GetServiceName(domain string) (string, bool) {
s.mutex.RLock()
service, exists := s.reverseMap[domain]
s.mutex.RUnlock()
return service, exists
}
func (m *Metrics) ListDomains() []string {
defer m.mutex.RUnlock()
domains := []string{}
m.mutex.RLock()
for domain := range m.db {
if strings.Contains(domain, ".") {
domains = append(domains, domain)
}
}
return domains
}
func (m *Metrics) Get(domain string) (Endpoints, bool) {
defer m.mutex.RUnlock()
endpoints := Endpoints{}
m.mutex.RLock()
_, exists := m.db[domain]
if exists {
for k, v := range m.db[domain] {
endpoints[k] = v
}
}
return endpoints, exists
}
func (m *Metrics) Set(domain string, endpoints Endpoints) {
m.mutex.Lock()
m.db[domain] = endpoints
m.mutex.Unlock()
}
func (m *Metrics) Flush() {
m.mutex.Lock()
m.db = map[string]Endpoints{}
m.mutex.Unlock()
}