+ 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 (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 ^ "/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, 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 ",
+ Int.toString uid,
+ " { jump user_",
+ uname,
+ suffix,
+ "; DROP; }\n"]);
+ (* Is there any point to splitting the rules like this? *)
+ TextIO.output (users_conf,
+ String.concat ("chain user_"
+ :: uname
+ :: suffix
+ :: " proto tcp {\n"
+ :: lines
+ @ ["}\n\n"]))
+ end handle OS.SysErr _ => print "Invalid user in firewall config, skipping.\n")
+ rules
+
+ fun write_tcp_in_conf (rules, outf, suffix) =
+ (* Lame hack: can't use iptables to restrict port binding,
+ punting on SELinux &c for now and just opening every
+ port any user requests *)
+
+ let
+ in
+ TextIO.output (outf, String.concat ["@def $WEBNODES = (",
+ (String.concatWith ", " (List.map (fn (_, ip) => ip)
+ (List.filter (fn (node, _) => List.exists (fn (n) => n = node) (List.map (fn (node, _) => node) (Config.Apache.webNodes_all @ Config.Apache.webNodes_admin)))
+ Config.nodeIps))),
+ ");\n\n"]);
+ 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 ("proto tcp {\n"
+ :: lines
+ @ ["}\n\n"]))
+ end handle OS.SysErr _ => print "Invalid user in firewall config, skipping.\n")
+ rules
+ end
+ in
+ write_tcp_in_conf (server_rules, users_tcp_in_conf, "_tcp_in");
+ write_user_tcp_conf (client_rules, users_tcp_out_conf, "_tcp_out");
+
+ TextIO.closeOut users_conf;
+ TextIO.closeOut users_tcp_out_conf;
+ TextIO.closeOut users_tcp_in_conf;