This repository has been archived by the owner on Jun 3, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
firewall.cljs
110 lines (93 loc) · 2.92 KB
/
firewall.cljs
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
(ns re-conf.resources.firewall
"Firewall management resources"
(:require-macros
[cljs.core.match :refer [match]]
[clojure.core.strint :refer (<<)])
(:require
[re-conf.resources.serialize :refer (call consumer)]
[re-conf.resources.common :refer (run)]
[re-conf.resources.log :refer (info debug error channel?)]
[cljs.core.async :refer [<! >! go chan]]
[re-conf.resources.facts :refer (os)]
[re-conf.resources.shell :refer (sh)]))
(defprotocol Firewall
(enable [this])
(disable [this])
(add [this rule])
(delete [this rule]))
(def ufw-bin
"/usr/sbin/ufw")
(defn- ufw-rule
"ufw add rule syntax from map"
[m]
{:pre [(m :port)]}
(match [(update m :port str)]
[{:from f :port p}] ["from" f "to" "any" "port" p]
[{:from f :to t :port p}] ["from" f "to" t "port" p]
[{:port p}] [p]))
(defrecord Ufw [pipe]
Firewall
(enable [this]
(debug "enable ufw" ::ufw)
(apply sh [ufw-bin "--force" "enable"]))
(disable [this]
(debug "disable ufw" ::ufw)
(apply sh [ufw-bin "--force" "disable"]))
(add [this rule]
(debug (<< "add rule ~{rule}") ::ufw)
(apply sh (into [ufw-bin "allow"] (ufw-rule rule))))
(delete [this rule]
(debug (<< "delete rule ~{rule}") ::ufw)
(apply sh (into [ufw-bin "delete"] (ufw-rule rule)))))
(def firewall-pipe (chan 10))
(defn ufw []
"Ufw provider"
(Ufw. firewall-pipe))
(defn- into-spec [m args]
(if (empty? args)
m
(let [a (first args)]
(cond
(map? a) (into-spec (assoc m :rule a) (rest args))
(channel? a) (into-spec (assoc m :ch a) (rest args))
(keyword? a) (into-spec (assoc m :state a) (rest args))
(fn? a) (into-spec (assoc m :provider (a)) (rest args))))))
(defn add-rule
"Serialized add-rule call"
[provider rule]
(call add provider rule))
(defn delete-rule
"Serialized delete-rule call"
[provider rule]
(call delete provider rule))
(defn rule
"Firewall Rule resource with optional provider and state parameters:
(rule {:port 22}) ; allow port 22
(rule {:port 22 :from \"10.0.0.1\"}) ; port from a network
(rule {:port 22} :absent) ; remove rule
(rule {:port 22} :present) ; explicit present
"
[& args]
(let [{:keys [ch rule state provider] :or {provider (ufw) state :present}} (into-spec {} args)
fns {:present add-rule :absent delete}]
(run ch (fns state) [provider rule])))
(defn enable-firewall
[provider]
(call enable provider))
(defn disable-firewall
[provider]
(call disable provider))
(defn firewall
"Firewall resource management
(firewall :present) ; enable firewall
(firewall :absent) ; disable firewall
"
[& args]
(let [{:keys [ch state provider] :or {provider (ufw) state :present}} (into-spec {} args)
fns {:present enable-firewall :absent disable-firewall}]
(run ch (fns state) [provider])))
(defn initialize
"Setup firewall resource serializing consumer"
[]
(go
(consumer firewall-pipe)))