Skip to content

Commit e961bd7

Browse files
committedOct 11, 2019
0.1.3 release
New features: - Disaster recovery: befw will set latest working rules if something goes wrong - Consisntency check: if somehow ipset or rules content is changed, befw will restore it
1 parent a4964a6 commit e961bd7

File tree

9 files changed

+127
-50
lines changed

9 files changed

+127
-50
lines changed
 

‎.gitignore

+2-12
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,2 @@
1-
# Binaries for programs and plugins
2-
*.exe
3-
*.exe~
4-
*.dll
5-
*.so
6-
*.dylib
7-
8-
# Test binary, build with `go test -c`
9-
*.test
10-
11-
# Output of the go coverage tool, specifically when used with LiteIDE
12-
*.out
1+
*.conf
2+
befw-*

‎CHANGELOG.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
### 0.1.3
2+
- befw now checks if its rules is consistent
3+
- befw now can recover firewall access if consul is dead with a hard-coded ( TOTO: configured ) networks
4+
5+
### 0.1.2
6+
- fix 0.0.0.0/0 centos7 ipset bug
7+
- befw-sync now wipes old records
8+
- documentation fixes
9+
- befw-sync timeouts & races fixed
10+
11+
### 0.1.1
12+
- Uses short hostnames instead of FQDN
13+
- Additional sleep(s) if errors repeat
14+
- Fix ipset refresh
15+
- Fix static ipset aliases
16+
117
### 0.1.0
218
- a huge documentation update
319
- befw-firewalld now supports configuration file
@@ -23,4 +39,4 @@
2339
### 0.0.2
2440
- Alias (befw/$alias$/*) support
2541
### 0.0.1
26-
- Initial version
42+
- Initial version

‎src/befw/config.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import (
2727
type config struct {
2828
ConsulAddr string
2929
ConsulDC string
30+
NodeName string
31+
NodeDC string
3032
ConsulToken string
3133
ServicesDir string
3234
IPSetDir string
@@ -44,7 +46,7 @@ type serviceClient struct {
4446
}
4547

4648
type service struct {
47-
ServiceName string `json:"Name"`
49+
ServiceName string `json:"name"`
4850
ServiceProtocol befwServiceProto `json:"protocol"`
4951
ServicePort uint16 `json:"port"`
5052
ServicePorts []port `json:"ports"`
@@ -116,6 +118,12 @@ func createConfig(configFile string) *config {
116118
if v, ok := kv["rules"]; ok {
117119
ret.RulesPath = v
118120
}
121+
if v, ok := kv["nodename"]; ok {
122+
ret.NodeName = v
123+
}
124+
if v, ok := kv["nodedc"]; ok {
125+
ret.NodeDC = v
126+
}
119127
if _, ok := kv["fail"]; ok {
120128
LogError("[Config] you must edit your Config file before proceed")
121129
}

‎src/befw/rules.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func cutIPSet(ipsetName string) string {
148148
if len(ipsetName) > 31 { // max size of links
149149
parts := strings.Split(ipsetName, "_")
150150
leftLength := 31 - len(parts[len(parts)-1]) // we can't reduce last part
151-
maxPartLen := int((leftLength/(len(parts)-1) - 1))
151+
maxPartLen := int(leftLength/(len(parts)-1) - 1)
152152
for i := 0; i < len(parts)-1; i++ {
153153
if len(parts[i]) > maxPartLen {
154154
parts[i] = string([]byte(parts[i])[0:maxPartLen]) // trim to size

‎src/befw/state.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,18 @@ func newState(configFile string) *state {
6161
if self, e := state.consulClient.Agent().Self(); e != nil {
6262
LogError("Can't connect to consul cluster. Error:", e.Error())
6363
} else {
64-
state.nodeDC = self["Config"]["Datacenter"].(string)
65-
state.nodeName = self["Config"]["NodeName"].(string)
64+
if cfg.NodeDC != "" {
65+
state.nodeDC = cfg.NodeDC
66+
} else {
67+
state.nodeDC = self["Config"]["Datacenter"].(string)
68+
}
69+
if cfg.NodeName != "" {
70+
state.nodeName = cfg.NodeName
71+
} else {
72+
state.nodeName = self["Config"]["NodeName"].(string)
73+
}
74+
state.nodeDC = strings.ToLower(state.nodeDC)
75+
state.nodeName = strings.ToLower(strings.Split(state.nodeName, ".")[0])
6676
}
6777
state.NodeServices = make([]service, 0)
6878
return state
@@ -335,9 +345,6 @@ func (state *state) generateKVPaths(newServiceName string) []string {
335345
fmt.Sprintf("befw/%s/%s/", state.nodeDC, newServiceName),
336346
fmt.Sprintf("befw/%s/", newServiceName),
337347
}
338-
if idx := strings.Index(state.nodeName, "."); idx > 0 {
339-
ret = append(ret, fmt.Sprintf("befw/%s/%s/%s/", state.nodeDC, state.nodeName[:idx], newServiceName))
340-
}
341348
return ret
342349
}
343350

‎src/befw/state_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestGenerateKVPaths(t *testing.T) {
3535
if len(p1) != 3 {
3636
t.Error("Len != 3 in p1")
3737
}
38-
if len(p2) != 4 {
39-
t.Error("Len != 4 in p2")
38+
if len(p2) != 3 {
39+
t.Error("Len != 3 in p2")
4040
}
4141
}

‎src/puppetdbsync/puppetdb.go

+6
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ func (conf *syncConfig) newSyncData(message string) *syncData {
154154
return nil
155155
}
156156
elems := strings.Split(message, "@")
157+
for i := 0; i < len(elems); i++ {
158+
elems[i] = strings.ToLower(elems[i]) // tolower
159+
}
157160
switch len(elems) {
158161
case 2:
159162
ret.service = elems[0]
@@ -173,6 +176,9 @@ func (conf *syncConfig) newSyncData(message string) *syncData {
173176
default:
174177
return nil
175178
}
179+
if ret.node != "" {
180+
ret.node = strings.Split(ret.node, ".")[0] // remove ..xxx
181+
}
176182
if conf.validate(ret) {
177183
return ret
178184
}

‎src/puppetdbsync/run.go

+5
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ func keepLock(config *syncConfig) {
8383
for {
8484
canRunMutex.Lock()
8585
canRun = config.manageSessionLock()
86+
if lastState != canRun {
87+
config.lastCounter = 999
88+
befw.LogInfo("[Syncer] We got lock - refreshing puppetdb")
89+
}
90+
lastState = canRun // state changed
8691
canRunMutex.Unlock()
8792
select {
8893
case <-exitChan:

‎src/puppetdbsync/sync.go

+73-28
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ func (conf *syncConfig) makeHotCache() {
140140
return
141141
} else {
142142
for _, node := range nodes {
143-
conf.cache.nodes[dc+"@"+node.Node] = nil
143+
nodeName := strings.Split(node.Node, ".")[0]
144+
conf.cache.nodes[dc+"@"+nodeName] = nil
144145
}
145146
}
146147
}
@@ -154,9 +155,7 @@ func (conf *syncConfig) writeSyncData(data *syncData) {
154155
defer conf.servicesWG.Done()
155156
path := fmt.Sprintf("%s/%s", data.service, data.value)
156157
if data.node != "" {
157-
//
158-
nodeShortHostName := data.node[:strings.Index(data.node, ".")]
159-
path = fmt.Sprintf("%s/%s", nodeShortHostName, path)
158+
path = fmt.Sprintf("%s/%s", data.node, path)
160159
}
161160
if data.dc != "" {
162161
path = fmt.Sprintf("%s/%s", data.dc, path)
@@ -178,45 +177,91 @@ func (conf *syncConfig) writeSyncData(data *syncData) {
178177
}
179178

180179
func (conf *syncConfig) manageSession() {
181-
nodeName := fmt.Sprintf("%s.%s", conf.consulDC, conf.nodeName)
182-
// 1. register main node
183-
conf.consulClient.Catalog().Register(&api.CatalogRegistration{
184-
Node: nodeName,
185-
Address: conf.nodeAddr,
186-
Datacenter: conf.consulDC,
187-
SkipNodeUpdate: true,
188-
}, nil)
189-
if conf.sessionID == "" {
190-
if sess, _, e := conf.consulClient.Session().CreateNoChecks(
191-
&api.SessionEntry{
192-
Node: nodeName,
193-
Name: "befw-sync",
194-
TTL: "30s",
195-
}, nil); e == nil {
196-
conf.sessionID = sess
180+
//nodeName := fmt.Sprintf("%s.%s", conf.consulDC, conf.nodeName)
181+
errcount := 0
182+
for errcount < 10 {
183+
//// 1. register main node
184+
if _, e := conf.consulClient.Catalog().Register(&api.CatalogRegistration{
185+
Node: conf.nodeName,
186+
Address: conf.nodeAddr,
187+
Datacenter: conf.consulDC,
188+
}, nil); e != nil {
189+
befw.LogWarning("[Syncer] can't register a node!")
197190
}
198-
} else {
199-
if se, _, e := conf.consulClient.Session().Info(conf.sessionID, nil); e != nil || se == nil {
200-
befw.LogDebug("[Syncer] Can't find session:", conf.sessionID)
201-
conf.sessionID = ""
202-
conf.manageSession() // a bit recursive
191+
befw.LogDebug("[Syncer] starting session creation")
192+
if conf.sessionID == "" {
193+
if sess, _, e := conf.consulClient.Session().CreateNoChecks(
194+
&api.SessionEntry{
195+
Node: conf.nodeName,
196+
Name: "befw-sync",
197+
TTL: "40s",
198+
}, &api.WriteOptions{Datacenter: conf.consulDC}); e == nil {
199+
conf.sessionID = sess
200+
} else {
201+
befw.LogWarning("[Syncer] Can't create session: ", e.Error())
202+
errcount++
203+
continue
204+
}
203205
} else {
204-
conf.consulClient.Session().Renew(conf.sessionID, nil)
206+
if se, _, e := conf.consulClient.Session().Info(conf.sessionID, nil); e != nil {
207+
conf.sessionID = ""
208+
befw.LogDebug("[Syncer] error while getting session: ", conf.sessionID, ", ", e.Error())
209+
errcount++
210+
continue
211+
} else if se == nil {
212+
conf.sessionID = ""
213+
befw.LogDebug("[Syncer] Can't find session:", conf.sessionID)
214+
errcount++
215+
continue
216+
}
217+
if se, _, e := conf.consulClient.Session().Renew(conf.sessionID, nil); e != nil {
218+
conf.sessionID = ""
219+
befw.LogDebug("[Syncer] error while renewning session: ", conf.sessionID, ", ", e.Error())
220+
errcount++
221+
continue
222+
} else if se == nil {
223+
conf.sessionID = ""
224+
befw.LogDebug("[Syncer] Can't find session:", conf.sessionID)
225+
errcount++
226+
continue
227+
}
205228
}
229+
break
206230
}
231+
befw.LogDebug("[Syncer] got session ", conf.sessionID)
207232
}
208233

234+
func (conf *syncConfig) getSessionHolder(session string) string {
235+
if se, _, e := conf.consulClient.Session().Info(session, nil); e == nil && se != nil {
236+
return fmt.Sprintf("%s@%s", se.Name, se.Node)
237+
}
238+
return ""
239+
}
240+
241+
var lastState bool
242+
209243
func (conf *syncConfig) manageSessionLock() bool {
210244
conf.manageSession()
211245
if conf.sessionID != "" {
212246
if v, _, e := conf.consulClient.KV().Acquire(
213247
&api.KVPair{Key: "befw/.lock",
214-
Value: []byte("ok"),
248+
Value: []byte(conf.nodeName),
215249
Session: conf.sessionID,
216-
}, nil); e != nil {
250+
}, &api.WriteOptions{Datacenter: conf.consulDC}); e != nil {
217251
befw.LogWarning("[Syncer] Can't create lock:", e.Error())
218252
return false
219253
} else {
254+
if !v {
255+
if kv, _, e := conf.consulClient.KV().Get("befw/.lock", nil); e == nil {
256+
if kv.Session != "" {
257+
if si := conf.getSessionHolder(kv.Session); si != "" {
258+
befw.LogInfo("[Syncer] key is locked by ", si)
259+
}
260+
}
261+
}
262+
} else {
263+
befw.LogInfo("[Syncer] Lock acquired by me")
264+
}
220265
return v
221266
}
222267
}

0 commit comments

Comments
 (0)