mecano
Version:
Common functions for system deployment.
226 lines (219 loc) • 7.29 kB
JavaScript
// Generated by CoffeeScript 1.7.1
var child, conditions, each, execute, misc;
each = require('each');
misc = require('./misc');
conditions = require('./misc/conditions');
child = require('./misc/child');
execute = require('./execute');
module.exports = function(goptions, options, callback) {
var finish, result, _ref;
_ref = misc.args(arguments), goptions = _ref[0], options = _ref[1], callback = _ref[2];
result = child();
finish = function(err, written) {
if (callback) {
callback(err, written);
}
return result.end(err, written);
};
misc.options(options, function(err, options) {
var executed;
if (err) {
return callback(err);
}
executed = 0;
return each(options).parallel(goptions.parallel).on('item', function(options, next) {
var cmd, cmd_add, cmd_modify, cmd_remove, crules, do_cmds, do_list, do_position, do_save;
crules = [];
cmd = function(cmd, rule) {
if (rule.protocol) {
cmd += " -p " + rule.protocol;
}
if (rule.source) {
cmd += " -s " + rule.source;
}
if (rule.destination) {
cmd += " -d " + rule.destination;
}
if (rule.target) {
cmd += " -j " + rule.target;
}
if (rule.dport) {
cmd += " --dport " + rule.dport;
}
if (rule.sport) {
cmd += " --sport " + rule.sport;
}
if (rule.state) {
cmd += " -m state --state " + rule.state;
}
if (rule.comment) {
cmd += " -m comment --comment \"" + rule.comment + "\"";
}
return cmd;
};
cmd_add = function(rule) {
return cmd("iptables -I " + rule.chain + " " + rule.rulenum, rule);
};
cmd_modify = function(rule) {
return cmd("iptables -R " + rule.chain + " " + rule.rulenum, rule);
};
cmd_remove = function(rule) {
return "iptables -D " + rule.chain + " " + rule.rulenum;
};
do_list = function() {
var chains;
chains = {};
return execute({
cmd: "iptables -L --line-numbers -nv",
ssh: options.ssh,
log: options.log,
stdout: options.stdout,
stderr: options.stderr
}, function(err, executed, stdout) {
var chain, columns, i, ichain, k, line, match, others, rule, v, _i, _j, _k, _len, _len1, _len2, _ref1, _ref2;
if (err) {
return next(err);
}
ichain = 0;
chain = null;
_ref1 = stdout.split(/\r\n|[\n\r\u0085\u2028\u2029]/g);
for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {
line = _ref1[i];
if (ichain === 0) {
match = /^Chain\s+(\w+)\s+.*$/.exec(line);
if (!match) {
return next(new Error("Invalid output: " + (JSON.stringify(stdout))));
}
chain = match[1];
ichain++;
continue;
}
if (ichain === 1) {
ichain++;
continue;
}
if (/^\s*$/.test(line)) {
ichain = 0;
continue;
}
columns = line.split(/\ +/);
rule = {
chain: chain
};
_ref2 = ['rulenum', 'packets', 'bytes', 'target', 'protocol', 'options', 'in-interface', 'out-interface', 'source', 'destination'];
for (i = _j = 0, _len1 = _ref2.length; _j < _len1; i = ++_j) {
k = _ref2[i];
rule[k] = columns[i];
}
others = columns.slice(10);
for (i = _k = 0, _len2 = others.length; _k < _len2; i = ++_k) {
v = others[i];
if (v === '/*') {
rule.comment = '';
while ((v = others[++i]) !== '*/') {
rule.comment += ' ' + v;
}
} else if (match = /^dpt:(\d+)$/.exec(v)) {
rule.dport = match[1];
} else if (v === '--state') {
rule.state = others[++i];
}
}
crules.push(rule);
}
if (crules.length === 0) {
return next(new Error("IPTables rules not loaded, (re)start iptables"));
}
return do_position();
});
};
do_position = function() {
var add_properties, crule, rule, _i, _j, _len, _len1, _ref1;
_ref1 = options.rules;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
rule = _ref1[_i];
if (rule.rulenum == null) {
rule.rulenum = {
chain: 'INPUT',
target: 'ACCEPT',
'in-interface': 'lo'
};
}
if (typeof rule.rulenum !== 'object') {
continue;
}
add_properties = misc.array.intersect(misc.iptables.add_properties, Object.keys(rule.rulenum));
for (_j = 0, _len1 = crules.length; _j < _len1; _j++) {
crule = crules[_j];
if (misc.object.equals(rule.rulenum, crule, add_properties)) {
rule.rulenum = '' + (parseInt(crule.rulenum, 10) + 1);
break;
}
}
if (!/\d+/.test(rule.rulenum)) {
if (typeof options.log === "function") {
options.log("No matching rule number, default to 1");
}
rule.rulenum = 1;
}
}
return do_cmds();
};
do_cmds = function() {
var add_properties, cmds, create, crule, rule, _i, _j, _len, _len1, _ref1;
cmds = [];
_ref1 = options.rules;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
rule = _ref1[_i];
create = true;
add_properties = misc.array.intersect(misc.iptables.add_properties, Object.keys(rule));
for (_j = 0, _len1 = crules.length; _j < _len1; _j++) {
crule = crules[_j];
if (misc.object.equals(rule, crule, add_properties)) {
create = false;
if (!misc.object.equals(rule, crule, misc.iptables.modify_properties)) {
cmds.push(cmd_modify(rule));
}
}
}
if (create) {
cmds.push(cmd_add(rule));
}
}
if (!cmds.length) {
return next();
}
return execute({
cmd: cmds.join(';'),
ssh: options.ssh,
log: options.log,
stdout: options.stdout,
stderr: options.stderr
}, function(err, executed, stdout) {
if (err) {
return next(err);
}
return do_save();
});
};
do_save = function() {
return execute({
cmd: "service iptables save",
ssh: options.ssh,
log: options.log,
stdout: options.stdout,
stderr: options.stderr
}, function(err, executed, stdout) {
if (!err) {
executed++;
}
return next(err);
});
};
return conditions.all(options, next, do_list);
}).on('both', function(err) {
return finish(err, executed);
});
});
return result;
};