DynamicRuleActions
package com.spawnlabs.server.dmfs;
import com.spawnlabs.server.dmfs.iptables.DmfsExecuteException;
import com.spawnlabs.server.dmfs.iptables.DmfsExecuteResult;
import com.spawnlabs.server.dmfs.iptables.IptablesStateViolationException;
import com.spawnlabs.server.dmfs.iptables.RuleExecutionException;
import com.spawnlabs.server.dmfs.iptables.RuleExecutor;
import com.spawnlabs.server.dmfs.template.ITemplateMgr;
import com.spawnlabs.server.dmfs.template.MissingTemplateArgumentException;
import com.spawnlabs.server.dmfs.template.TemplateNotFoundException;
import com.spawnlabs.server.dmfs.template.TemplateReadingException;
import com.spawnlabs.server.spawnsvc.ConfigProperties;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import static com.spawnlabs.server.dmfs.DmfsNames.*;
import static com.spawnlabs.server.dmfs.template.TemplateUtil.CommandType.iptables;
import static com.spawnlabs.server.dmfs.template.TemplateUtil.CommandType.restore;
/**
*
*
*/
public class DynamicRuleActions {
public static final String ruleAlreadyTight = "This rule was already tight: ";
public static final String ruleAlreadyRelaxed = "This rule was already relaxed: ";
private ConfigProperties config;
private RuleExecutor ruleExecutor;
private ITemplateMgr templateMgr;
public DynamicRuleActions(ConfigProperties config, ITemplateMgr templateMgr, RuleExecutor ruleExecutor) {
this.config = config;
this.ruleExecutor = ruleExecutor;
this.templateMgr = templateMgr;
}
public DmfsExecuteResult fullPlaySessionStart(String token, InetAddress rips, InetAddress ripn, int lportn) throws
RuleExecutionException,
TemplateReadingException,
TemplateNotFoundException,
MissingTemplateArgumentException,
IptablesStateViolationException {
// Create map of args
HashMap<String, Object> args = new HashMap<String, Object>();
args.put(TOKEN, token);
args.put(RIPS, rips.getHostAddress());
args.put(RIPN, ripn.getHostAddress());
args.put(LPORTN, lportn);
args.put(LIPN, config.getProperty(LIPN));
args.put(LIPS, config.getProperty(LIPS));
args.put(RPORTS, config.getIntegerProperty(RPORTS));
args.put(LPORTS, config.getIntegerProperty(LPORTS));
String rules = templateMgr.getRulesFor(FULL_PLAY_SESSION, START, restore, args);
return ruleExecutor.applyStartRules(rules);
}
public DmfsExecuteResult fullPlaySessionTighten(String token, int rportn) throws
RuleExecutionException,
TemplateReadingException,
TemplateNotFoundException,
MissingTemplateArgumentException {
// List the existing rules
DmfsExecuteResult listResult = ruleExecutor.listForwardRules(token);
ParsedRuleValues parsedRuleValues = new ParsedRuleValues(listResult.getCommandOutput(), 3, 4);
if (parsedRuleValues.getLines().length == 4) {
// There is a relax rule in place. Re-tighten by deleting it.
return ruleExecutor.deleteForwardRuleForTightening(token);
} // else numLines == 3
// Parse the rules to determine: RIPN, RIPS, and RPORTS
parsedRuleValues.invoke();
if (parsedRuleValues.getRportn() != -1) {
// This rule is already tight. no-op
return new DmfsExecuteResult(listResult.getCommandOutput(), listResult.getCommandLine()).putMessage(ruleAlreadyTight + token);
}
// ==================================================================================================================
// There is no relax rule in place, and the existing rule is relaxed. Replace that rule with a tighter one
// ==================================================================================================================
// Assemble the substitution params for Velocity
// Create map of args
HashMap<String, Object> args = new HashMap<String, Object>();
args.put(TOKEN, token);
args.put(RIPN, parsedRuleValues.getRipn());
args.put(RPORTN, rportn);
args.put(RIPS, parsedRuleValues.getRips());
args.put(RPORTS, parsedRuleValues.getRports());
// Get the template parsed
String tightenRule = templateMgr.getRulesFor(FULL_PLAY_SESSION, TIGHTEN, iptables, args);
// Now execute the command to tighten
return ruleExecutor.replaceForwardRuleForTightening(token, tightenRule);
}
public DmfsExecuteResult fullPlaySessionRelax(String token) throws
TemplateReadingException,
RuleExecutionException,
TemplateNotFoundException,
MissingTemplateArgumentException {
// List the existing rules
DmfsExecuteResult listResult = ruleExecutor.listForwardRules(token);
ParsedRuleValues parsedRuleValues = new ParsedRuleValues(listResult.getCommandOutput(), 3, 4);
if (parsedRuleValues.getLines().length == 4) {
// 2 rules exist: no-op
return new DmfsExecuteResult(listResult.getCommandOutput(), listResult.getCommandLine()).putMessage(ruleAlreadyRelaxed + token);
}// else numLines == 3
// Parse the rules to determine: RIPN, RIPS, and RPORTS (and possibly RPORTN)
parsedRuleValues.invoke();
if (parsedRuleValues.getRportn() == -1) {
// There are 3 lines and 1 rule, but the rule is already relaxed (no "spt:" designated)
return new DmfsExecuteResult(listResult.getCommandOutput(), listResult.getCommandLine()).putMessage(ruleAlreadyRelaxed + token);
}
// ===============================================================================================
// There is no relax rule in place, and the existing rule is tightened. Insert a relax rule
// ===============================================================================================
// Assemble the substitution params for Velocity
// Create map of args
HashMap<String, Object> args = new HashMap<String, Object>();
args.put(TOKEN, token);
args.put(RIPN, parsedRuleValues.getRipn());
args.put(RIPS, parsedRuleValues.getRips());
args.put(RPORTS, parsedRuleValues.getRports());
// Get the template parsed
String relaxRule = templateMgr.getRulesFor(FULL_PLAY_SESSION, RELAX, iptables, args);
// Now execute the command to relax
return ruleExecutor.insertForwardRuleForRelaxing(token, relaxRule);
}
public DmfsExecuteResult fullPlaySessionStop(String token) throws
TemplateReadingException,
TemplateNotFoundException,
MissingTemplateArgumentException,
RuleExecutionException,
IptablesStateViolationException {
// Create map of args
HashMap<String, Object> args = new HashMap<String, Object>();
args.put(TOKEN, token);
String rules = templateMgr.getRulesFor(FULL_PLAY_SESSION, STOP, restore, args);
return ruleExecutor.applyStopRules(rules);
}
public DmfsExecuteResult fullPlaySessionQuery(String token, boolean showRoute) throws
TemplateReadingException,
TemplateNotFoundException,
MissingTemplateArgumentException,
RuleExecutionException,
IptablesStateViolationException {
// Create map of args
HashMap<String, Object> args = new HashMap<String, Object>();
args.put(TOKEN, token);
String rules = templateMgr.getRulesFor(FULL_PLAY_SESSION, QUERY, restore, args);
DmfsExecuteResult result;
try {
result = ruleExecutor.queryPlaySession(rules);
} catch (IptablesStateViolationException e) {
if (e.getCode() == DmfsOperationException.IPTABLES_CONNECTION_DOESNT_EXIST) {
// If we get this exception, throw an exception just like the one we caught, except
// modify the message to include the token (which, at that level in the stack, we didn't know)
throw new IptablesStateViolationException(e.getCode(), (DmfsExecuteException) e.getCause(), "No connection exists for token: [" + token + "]", e.getRules());
}
throw e;
}
/* Sample output:
Chain XYZ (2 references)
num pkts bytes target prot opt in out source destination
1 0 0 DNAT udp -- * * 0.0.0.0/0 10.0.11.75 udp dpt:64600 to:10.0.111.76:64200
2 0 0 DNAT tcp -- * * 0.0.0.0/0 10.0.11.75 tcp dpt:64600 to:10.0.111.76:64200
3 0 0 SNAT udp -- * * 0.0.0.0/0 10.0.111.76 udp dpt:64200 to:10.0.111.75:64400
4 0 0 SNAT tcp -- * * 0.0.0.0/0 10.0.111.76 tcp dpt:64200 to:10.0.111.75:64400
Chain XYZ (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT udp -- * * 10.0.11.75 10.0.111.76 udp dpt:64200
*/
result.setMessage(result.getMessage() + " | " + result.getCommandOutput());
if (showRoute) {
}
return result; // SERVER-569
}
public DmfsExecuteResult queryAllPlaySessions() throws RuleExecutionException {
DmfsExecuteResult result = ruleExecutor.queryAllPlaySessions();
boolean hasConnections = false;
for (String key : result.getExtraValues().keySet()) {
if (key.startsWith(DmfsNames.TOKEN_PREFIX)) {
hasConnections = true;
}
}
if (!hasConnections) {
result.setMessage("No active connections.");
}
return result;
}
public DmfsExecuteResult applyRuleTemplate(String connectionClass, String templateName, Map<String, String> params) {
return null;
}
protected static class ParsedRuleValues {
private String existingRules;
private final int minNumRules;
private final int maxNumRules;
private String sourceIp;
private String destIp;
private int destPort;
private int srcPort = -1;
private String[] lines;
public ParsedRuleValues(String existingRules, int minNumRules, int maxNumRules) throws TemplateReadingException {
this.existingRules = existingRules;
this.minNumRules = minNumRules;
this.maxNumRules = maxNumRules;
lines = getLines();
}
public String getRipn() {
return sourceIp;
}
public String getRips() {
return destIp;
}
public int getRports() {
return destPort;
}
public int getRportn() {
return srcPort;
}
public ParsedRuleValues invoke() throws TemplateReadingException, RuleExecutionException {
try {
return parse();
} catch (NumberFormatException e) {
throw new TemplateReadingException(DmfsProcessException.TEMPLATE_PARSING_EXCEPTION,
e,
"There was a problem parsing out RIPN, RIPS, and RPORTS from the template. This could be a " +
"code problem, or could be that the rule list is incorrectly-formed. Existing Rules: " +
"[" + existingRules + "]");
}
}
public ParsedRuleValues parse() throws RuleExecutionException {
int i;
for (i = 0; i < lines.length; i++) {
String s = lines[i];
if (s.startsWith(RuleExecutor.ARG_RULENUM)) {
break;
}
}
sourceIp = null;
destIp = null;
destPort = -1;
StringTokenizer st = new StringTokenizer(lines[i], SPC, false);
while (st.hasMoreElements()) {
String t = (String) st.nextElement();
if (t.contains(".")) {
if (sourceIp == null) {
sourceIp = t;
}
else {
destIp = t;
}
}
else if (t.startsWith("dpt:")) {
destPort = Integer.parseInt(t.substring("dpt:".length(), t.length()));
}
else if (t.startsWith("spt:")) {
srcPort = Integer.parseInt(t.substring("spt:".length(), t.length()));
}
}
return this;
}
private String[] getLines() throws TemplateReadingException {
if (lines == null) {
lines = existingRules.split(ls);
if (lines.length < minNumRules || lines.length > maxNumRules) {
throw new TemplateReadingException(DmfsProcessException.TEMPLATE_PARSING_EXCEPTION,
"Listed lines were expected to be between: " + minNumRules + " and " + maxNumRules + ". Instead, were " + lines.length + ". Full rules: [" + existingRules + "]",
true);
}
}
return lines;
}
}
}