structure Firewall :> FIREWALL = struct
-type firewall_rules = { server_rules : (string list DataStructures.StringMap.map),
- client_rules : (string list DataStructures.StringMap.map)}
+type firewall_rules = { server_rules : ((string * string) list DataStructures.StringMap.map),
+ client_rules : ((string * string) list DataStructures.StringMap.map)}
structure StringMap = DataStructures.StringMap
-fun parseRules _ =
+fun parseRules () =
let
val inf = TextIO.openIn Config.Firewall.firewallRules
val out_lines = ref StringMap.empty
val in_lines = ref StringMap.empty
- fun confLine r (uname, line) =
+ fun confLine r (node, uname, line) =
let
- val line = String.concat ["\t", line, "\n"]
+ val line = (node, String.concat ["\t", line, "\n"])
val lines = case StringMap.find (!r, uname) of
NONE => []
| SOME lines => lines
NONE => ()
| SOME line =>
case String.tokens Char.isSpace line of
- uname :: rest =>
+ node :: uname :: rest =>
(case rest of
"Client" :: ports :: hosts =>
- confLine_out (uname, String.concat ["dport ", parsePorts ports, parseHosts "daddr" hosts, " ACCEPT;"])
+ confLine_out (node, uname, String.concat ["dport ", parsePorts ports, parseHosts "daddr" hosts, " ACCEPT;"])
| "Server" :: ports :: hosts =>
- confLine_in (uname, String.concat ["dport ", parsePorts ports, parseHosts "daddr" hosts, " ACCEPT;"])
+ confLine_in (node, uname, String.concat ["dport ", parsePorts ports, parseHosts "daddr" hosts, " ACCEPT;"])
| ["LocalServer", ports] =>
- confLine_in (uname, String.concat ["saddr $WE dport ", parsePorts ports, " ACCEPT;"])
+ confLine_in (node, uname, String.concat ["saddr $WE dport ", parsePorts ports, " ACCEPT;"])
| _ => print "Invalid config line\n";
loop ())
| _ => loop ()
let
val rules = parseRules ()
in
- getOpt (StringMap.find (#server_rules rules, uname), []) @ getOpt (StringMap.find (#client_rules rules, uname), [])
+ List.map (fn (n,r) => r ^ " #host: " ^ n) (getOpt (StringMap.find (#server_rules rules, uname), []) @ getOpt (StringMap.find (#client_rules rules, uname), []))
end
fun generateFirewallConfig {server_rules, client_rules} =
-(* rule generation must happen on the node (not really, but I'd rather
- avoid codifying that uids must be consistent between hosts) *)
+ (* rule generation must happen on the node (mandating the even
+ service users be pts users would make it possible to do on the
+ server, but that's not happening any time soon) *)
let
val users_tcp_out_conf = TextIO.openOut (Config.Firewall.firewallDir ^ "/users_tcp_out.conf")
val users_tcp_in_conf = TextIO.openOut (Config.Firewall.firewallDir ^ "/users_tcp_in.conf")
- val users_conf = TextIO.openOut (Config.Firewall.firewallDir ^ "/users.conf")
+ val users_conf = TextIO.openOut (Config.Firewall.firewallDir ^ "/user_chains.conf")
+
+ fun filter_node_rules lines =
+ (* filter out rules for other hosts here... really not
+ ideal, but it should work for the time being *)
+ List.map (fn (node, line) => line)
+ (List.filter (fn (node, line) => node = Slave.hostname ()) lines)
fun write_user_tcp_conf (rules, outf, suffix) =
- StringMap.appi (fn (uname, lines) =>
+ StringMap.appi (fn (uname, rules) =>
let
val uid = SysWord.toInt (Posix.ProcEnv.uidToWord (Posix.SysDB.Passwd.uid (Posix.SysDB.getpwnam uname)))
+ val lines = filter_node_rules rules
in
TextIO.output (outf, String.concat
["mod owner uid-owner ",
" { goto user_",
uname,
suffix,
- "; goto lreject; }\n"]);
+ "; DROP; }\n"]);
(* Is there any point to splitting the rules like this? *)
TextIO.output (users_conf,
String.concat ("chain user_"