cloudstack/scripts/vm/network/security_group.py
Radoslaw Smigielski 0383803188 scripts: Fix security_group.py handling of args and unknown commands
Checks the args length, doesn't throw IndexError when no args
passed. Also logs to security_group.log when executed with no args or unknown
command.

Review: https://reviews.apache.org/r/9588
Reviewed-by: Rohit Yadav <bhaisaab@apache.org>

Signed-off-by: Rohit Yadav <bhaisaab@apache.org>
2013-02-26 14:12:49 +05:30

839 lines
30 KiB
Python
Executable File

#!/usr/bin/python
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import cloud_utils
from cloud_utils import Command
from cloudutils.configFileOps import configFileOps
import logging
import sys
import os
import xml.dom.minidom
from optparse import OptionParser, OptionGroup, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError
import re
iptables = Command("iptables")
bash = Command("/bin/bash")
virsh = Command("virsh")
ebtablessave = Command("ebtables-save")
ebtables = Command("ebtables")
def execute(cmd):
logging.debug(cmd)
return bash("-c", cmd).stdout
def can_bridge_firewall(privnic):
try:
execute("which iptables")
except:
print "no iptables on your host machine"
sys.exit(1)
try:
execute("which ebtables")
except:
print "no ebtables on your host machine"
sys.exit(2)
if not os.path.exists('/var/run/cloud'):
os.makedirs('/var/run/cloud')
cleanup_rules_for_dead_vms()
cleanup_rules()
return True
'''
def ipset(ipsetname, proto, start, end, ips):
try:
check_call(['ipset', '-N', ipsetname, 'iptreemap'])
except:
logging.debug("ipset chain already exists" + ipsetname)
result = True
ipsettmp = ''.join(''.join(ipsetname.split('-')).split('_')) + str(int(time.time()) % 1000)
try:
check_call(['ipset', '-N', ipsettmp, 'iptreemap'])
for ip in ips:
try:
check_call(['ipset', '-A', ipsettmp, ip])
except CommandException, cex:
if cex.reason.rfind('already in set') == -1:
raise
check_call(['ipset', '-W', ipsettmp, ipsetname])
check_call(['ipset', '-X', ipsettmp])
except:
logging.debug("Failed to program ipset " + ipsetname)
result = False
return result
'''
def destroy_network_rules_for_vm(vm_name, vif=None):
vmchain = vm_name
vmchain_egress = egress_chain_name(vm_name)
vmchain_default = None
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
if vm_name.startswith('i-') or vm_name.startswith('r-'):
vmchain_default = '-'.join(vm_name.split('-')[:-1]) + "-def"
destroy_ebtables_rules(vmchain, vif)
try:
if vmchain_default != None:
execute("iptables -F " + vmchain_default)
except:
logging.debug("Ignoring failure to delete chain " + vmchain_default)
try:
if vmchain_default != None:
execute("iptables -X " + vmchain_default)
except:
logging.debug("Ignoring failure to delete chain " + vmchain_default)
try:
execute("iptables -F " + vmchain)
except:
logging.debug("Ignoring failure to delete chain " + vmchain)
try:
execute("iptables -X " + vmchain)
except:
logging.debug("Ignoring failure to delete chain " + vmchain)
try:
execute("iptables -F " + vmchain_egress)
except:
logging.debug("Ignoring failure to delete chain " + vmchain_egress)
try:
execute("iptables -X " + vmchain_egress)
except:
logging.debug("Ignoring failure to delete chain " + vmchain_egress)
if vif is not None:
try:
dnats = execute("iptables -t nat -S | grep " + vif + " | sed 's/-A/-D/'").split("\n")
for dnat in dnats:
try:
execute("iptables -t nat " + dnat)
except:
logging.debug("Igoring failure to delete dnat: " + dnat)
except:
pass
remove_rule_log_for_vm(vm_name)
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]:
return 'true'
return 'true'
def destroy_ebtables_rules(vm_name, vif):
delcmd = "ebtables -t nat -L PREROUTING | grep " + vm_name
delcmds = []
try:
delcmds = execute(delcmd).split('\n')
delcmds.pop()
delcmds = ["-D PREROUTING " + x for x in delcmds ]
except:
pass
postcmds = []
try:
postcmd = "ebtables -t nat -L POSTROUTING | grep " + vm_name
postcmds = execute(postcmd).split('\n')
postcmds.pop()
postcmds = ["-D POSTROUTING " + x for x in postcmds]
except:
pass
delcmds += postcmds
for cmd in delcmds:
try:
execute("ebtables -t nat " + cmd)
except:
logging.debug("Ignoring failure to delete ebtables rules for vm " + vm_name)
chains = [vm_name+"-in", vm_name+"-out"]
for chain in chains:
try:
execute("ebtables -t nat -F " + chain)
execute("ebtables -t nat -X " + chain)
except:
logging.debug("Ignoring failure to delete ebtables chain for vm " + vm_name)
def default_ebtables_rules(vm_name, vm_ip, vm_mac, vif):
vmchain_in = vm_name + "-in"
vmchain_out = vm_name + "-out"
for chain in [vmchain_in, vmchain_out]:
try:
execute("ebtables -t nat -N " + chain)
except:
execute("ebtables -t nat -F " + chain)
try:
# -s ! 52:54:0:56:44:32 -j DROP
execute("ebtables -t nat -A PREROUTING -i " + vif + " -j " + vmchain_in)
execute("ebtables -t nat -A POSTROUTING -o " + vif + " -j " + vmchain_out)
except:
logging.debug("Failed to program default rules")
return 'false'
try:
execute("ebtables -t nat -A " + vmchain_in + " -s ! " + vm_mac + " -j DROP")
execute("ebtables -t nat -A " + vmchain_in + " -p ARP -s ! " + vm_mac + " -j DROP")
execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-mac-src ! " + vm_mac + " -j DROP")
if vm_ip is not None:
execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-ip-src ! " + vm_ip + " -j DROP")
execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-op Request -j ACCEPT")
execute("ebtables -t nat -A " + vmchain_in + " -p ARP --arp-op Reply -j ACCEPT")
execute("ebtables -t nat -A " + vmchain_in + " -p ARP -j DROP")
except:
logging.exception("Failed to program default ebtables IN rules")
return 'false'
try:
execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Reply --arp-mac-dst ! " + vm_mac + " -j DROP")
if vm_ip is not None:
execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-ip-dst ! " + vm_ip + " -j DROP")
execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Request -j ACCEPT")
execute("ebtables -t nat -A " + vmchain_out + " -p ARP --arp-op Reply -j ACCEPT")
execute("ebtables -t nat -A " + vmchain_out + " -p ARP -j DROP")
except:
logging.debug("Failed to program default ebtables OUT rules")
return 'false'
def default_network_rules_systemvm(vm_name, localbrname):
bridges = getBridges(vm_name)
domid = getvmId(vm_name)
vmchain = vm_name
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
try:
execute("iptables -N " + vmchain)
except:
execute("iptables -F " + vmchain)
for bridge in bridges:
if bridge != localbrname:
if not addFWFramework(bridge):
return False
brfw = "BF-" + bridge
vifs = getVifsForBridge(vm_name, bridge)
for vif in vifs:
try:
execute("iptables -A " + brfw + "-OUT" + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -j " + vmchain)
execute("iptables -A " + brfw + "-IN" + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -j " + vmchain)
execute("iptables -A " + vmchain + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -j RETURN")
except:
logging.debug("Failed to program default rules")
return 'false'
execute("iptables -A " + vmchain + " -j ACCEPT")
if write_rule_log_for_vm(vm_name, '-1', '_ignore_', domid, '_initial_', '-1') == False:
logging.debug("Failed to log default network rules for systemvm, ignoring")
return 'true'
def default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname):
if not addFWFramework(brname):
return False
vmName = vm_name
brfw = "BF-" + brname
domID = getvmId(vm_name)
delete_rules_for_vm_in_bridge_firewall_chain(vmName)
vmchain = vm_name
vmchain_egress = egress_chain_name(vm_name)
vmchain_default = '-'.join(vmchain.split('-')[:-1]) + "-def"
destroy_ebtables_rules(vmName, vif)
try:
execute("iptables -N " + vmchain)
except:
execute("iptables -F " + vmchain)
try:
execute("iptables -N " + vmchain_egress)
except:
execute("iptables -F " + vmchain_egress)
try:
execute("iptables -N " + vmchain_default)
except:
execute("iptables -F " + vmchain_default)
try:
execute("iptables -A " + brfw + "-OUT" + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -j " + vmchain_default)
execute("iptables -A " + brfw + "-IN" + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -j " + vmchain_default)
execute("iptables -A " + vmchain_default + " -m state --state RELATED,ESTABLISHED -j ACCEPT")
#allow dhcp
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -p udp --dport 67 --sport 68 -j ACCEPT")
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -p udp --dport 68 --sport 67 -j ACCEPT")
#don't let vm spoof its ip address
if vm_ip is not None:
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -p udp --dport 53 -j RETURN ")
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -j " + vmchain_egress)
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -j " + vmchain)
execute("iptables -A " + vmchain + " -j DROP")
except:
logging.debug("Failed to program default rules for vm " + vm_name)
return 'false'
default_ebtables_rules(vmchain, vm_ip, vm_mac, vif)
if vm_ip is not None:
if write_rule_log_for_vm(vmName, vm_id, vm_ip, domID, '_initial_', '-1') == False:
logging.debug("Failed to log default network rules, ignoring")
logging.debug("Programmed default rules for vm " + vm_name)
return 'true'
def post_default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname, dhcpSvr, hostIp, hostMacAddr):
vmchain_default = '-'.join(vm_name.split('-')[:-1]) + "-def"
vmchain_in = vm_name + "-in"
vmchain_out = vm_name + "-out"
domID = getvmId(vm_name)
try:
execute("iptables -I " + vmchain_default + " 4 -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -j ACCEPT")
except:
pass
try:
execute("iptables -t nat -A PREROUTING -p tcp -m physdev --physdev-in " + vif + " -m tcp --dport 80 -d " + dhcpSvr + " -j DNAT --to-destination " + hostIp + ":80")
except:
pass
try:
execute("ebtables -t nat -I " + vmchain_in + " -p IPv4 --ip-protocol tcp --ip-destination-port 80 --ip-dst " + dhcpSvr + " -j dnat --to-destination " + hostMacAddr)
except:
pass
try:
execute("ebtables -t nat -I " + vmchain_in + " 4 -p ARP --arp-ip-src ! " + vm_ip + " -j DROP")
except:
pass
try:
execute("ebtables -t nat -I " + vmchain_out + " 2 -p ARP --arp-ip-dst ! " + vm_ip + " -j DROP")
except:
pass
if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domID, '_initial_', '-1') == False:
logging.debug("Failed to log default network rules, ignoring")
def delete_rules_for_vm_in_bridge_firewall_chain(vmName):
vm_name = vmName
if vm_name.startswith('i-') or vm_name.startswith('r-'):
vm_name = '-'.join(vm_name.split('-')[:-1])
vmchain = vm_name
delcmd = "iptables-save | grep BF | grep " + vmchain + " | grep physdev-is-bridged | sed 's/-A/-D/'"
delcmds = execute(delcmd).split('\n')
delcmds.pop()
for cmd in delcmds:
try:
execute("iptables " + cmd)
except:
logging.exception("Ignoring failure to delete rules for vm " + vmName)
def rewrite_rule_log_for_vm(vm_name, new_domid):
logfilename = "/var/run/cloud/" + vm_name +".log"
if not os.path.exists(logfilename):
return
lines = (line.rstrip() for line in open(logfilename))
[_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1']
for line in lines:
[_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',')
break
write_rule_log_for_vm(_vmName, _vmID, '0.0.0.0', new_domid, _signature, '-1')
def get_rule_log_for_vm(vmName):
vm_name = vmName;
logfilename = "/var/run/cloud/" + vm_name +".log"
if not os.path.exists(logfilename):
return ''
lines = (line.rstrip() for line in open(logfilename))
[_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1']
for line in lines:
[_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',')
break
return ','.join([_vmName, _vmID, _vmIP, _domID, _signature, _seqno])
def check_domid_changed(vmName):
curr_domid = '-1'
try:
curr_domid = getvmId(vmName)
if (curr_domid is None) or (not curr_domid.isdigit()):
curr_domid = '-1'
except:
pass
logfilename = "/var/run/cloud/" + vmName +".log"
if not os.path.exists(logfilename):
return ['-1', curr_domid]
lines = (line.rstrip() for line in open(logfilename))
[_vmName,_vmID,_vmIP,old_domid,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1']
for line in lines:
[_vmName,_vmID,_vmIP,old_domid,_signature,_seqno] = line.split(',')
break
return [curr_domid, old_domid]
def network_rules_for_rebooted_vm(vmName):
vm_name = vmName
[curr_domid, old_domid] = check_domid_changed(vm_name)
if curr_domid == old_domid:
return True
if old_domid == '-1':
return True
if curr_domid == '-1':
return True
logging.debug("Found a rebooted VM -- reprogramming rules for " + vm_name)
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
brName = execute("iptables-save |grep physdev-is-bridged |grep FORWARD |grep BF |grep '\-o' |awk '{print $9}' | head -1").strip()
if brName is None or brName is "":
brName = "cloudbr0"
else:
brName = re.sub("^BF-", "", brName)
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]:
default_network_rules_systemvm(vm_name, brName)
return True
vmchain = vm_name
vmchain_default = '-'.join(vmchain.split('-')[:-1]) + "-def"
vifs = getVifs(vmName)
logging.debug(vifs, brName)
for v in vifs:
execute("iptables -A " + "BF-" + brName + "-IN " + " -m physdev --physdev-is-bridged --physdev-in " + v + " -j "+ vmchain_default)
execute("iptables -A " + "BF-" + brName + "-OUT " + " -m physdev --physdev-is-bridged --physdev-out " + v + " -j "+ vmchain_default)
#change antispoof rule in vmchain
try:
delcmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev | sed 's/-A/-D/'"
inscmd = "iptables-save |grep '\-A " + vmchain_default + "' | grep physdev | sed -r 's/vnet[0-9]+/ " + vifs[0] + "/' | sed 's/-A/-I/'"
ipts = []
for cmd in [delcmd, inscmd]:
logging.debug(cmd)
cmds = execute(cmd).split('\n')
cmds.pop()
for c in cmds:
ipt = "iptables " + c
ipts.append(ipt)
for ipt in ipts:
try:
execute(ipt)
except:
logging.debug("Failed to rewrite antispoofing rules for vm " + vm_name)
except:
logging.debug("No rules found for vm " + vm_name)
rewrite_rule_log_for_vm(vm_name, curr_domid)
return True
def get_rule_logs_for_vms():
cmd = "virsh list|grep running |awk '{print $2}'"
vms = bash("-c", cmd).stdout.split("\n")
result = []
try:
for name in vms:
name = name.rstrip()
if 1 not in [ name.startswith(c) for c in ['r-', 's-', 'v-', 'i-'] ]:
continue
network_rules_for_rebooted_vm(name)
if name.startswith('i-'):
log = get_rule_log_for_vm(name)
result.append(log)
except:
logging.debug("Failed to get rule logs, better luck next time!")
print ";".join(result)
def cleanup_rules_for_dead_vms():
return True
def cleanup_rules():
try:
chainscmd = "iptables-save | grep '^:' | grep -v '.*-def' | grep -v '.*-eg' | awk '{print $1}' | cut -d':' -f2"
chains = execute(chainscmd).split('\n')
cleanup = []
for chain in chains:
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]:
vm_name = chain
cmd = "virsh list |grep " + vm_name
try:
result = execute(cmd)
except:
result = None
if result == None or len(result) == 0:
logging.debug("chain " + chain + " does not correspond to a vm, cleaning up")
cleanup.append(vm_name)
continue
if result.find("running") == -1:
logging.debug("vm " + vm_name + " is not running, cleaning up")
cleanup.append(vm_name)
chainscmd = "ebtables-save |grep :i |awk '{print $1}' |sed -e 's/\-in//g' |sed -e 's/\-out//g' |sed -e 's/^://g'"
chains = execute(chainscmd).split('\n')
for chain in chains:
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]:
vm_name = chain
cmd = "virsh list |grep " + vm_name
try:
result = execute(cmd)
except:
result = None
if result == None or len(result) == 0:
logging.debug("chain " + chain + " does not correspond to a vm, cleaning up")
cleanup.append(vm_name)
continue
if result.find("running") == -1:
logging.debug("vm " + vm_name + " is not running, cleaning up")
cleanup.append(vm_name)
for vmname in cleanup:
destroy_network_rules_for_vm(vmname)
logging.debug("Cleaned up rules for " + str(len(cleanup)) + " chains")
except:
logging.debug("Failed to cleanup rules !")
def check_rule_log_for_vm(vmName, vmId, vmIP, domID, signature, seqno):
vm_name = vmName;
logfilename = "/var/run/cloud/" + vm_name +".log"
if not os.path.exists(logfilename):
return [True, True, True, True, True, True]
try:
lines = (line.rstrip() for line in open(logfilename))
except:
logging.debug("failed to open " + logfilename)
return [True, True, True, True, True, True]
[_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = ['_', '-1', '_', '-1', '_', '-1']
try:
for line in lines:
[_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',')
break
except:
logging.debug("Failed to parse log file for vm " + vm_name)
remove_rule_log_for_vm(vm_name)
return [True, True, True, True, True, True]
return [(vm_name != _vmName), (vmId != _vmID), (vmIP != _vmIP), (domID != _domID), (signature != _signature),(seqno != _seqno)]
def write_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno):
vm_name = vmName
logfilename = "/var/run/cloud/" + vm_name +".log"
logging.debug("Writing log to " + logfilename)
logf = open(logfilename, 'w')
output = ','.join([vmName, vmID, vmIP, domID, signature, seqno])
result = True
try:
logf.write(output)
logf.write('\n')
except:
logging.debug("Failed to write to rule log file " + logfilename)
result = False
logf.close()
return result
def remove_rule_log_for_vm(vmName):
vm_name = vmName
logfilename = "/var/run/cloud/" + vm_name +".log"
result = True
try:
os.remove(logfilename)
except:
logging.debug("Failed to delete rule log file " + logfilename)
result = False
return result
def egress_chain_name(vm_name):
return vm_name + "-eg"
def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif, brname):
try:
vmName = vm_name
domId = getvmId(vmName)
changes = []
changes = check_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno)
if not 1 in changes:
logging.debug("Rules already programmed for vm " + vm_name)
return 'true'
if changes[0] or changes[1] or changes[2] or changes[3]:
default_network_rules(vmName, vm_id, vm_ip, vmMac, vif, brname)
if rules == "" or rules == None:
lines = []
else:
lines = rules.split(';')[:-1]
logging.debug(" programming network rules for IP: " + vm_ip + " vmname=" + vm_name)
vmchain = vm_name
execute("iptables -F " + vmchain)
egress_vmchain = egress_chain_name(vm_name)
execute("iptables -F " + egress_vmchain)
egressrule = 0
for line in lines:
tokens = line.split(':')
if len(tokens) != 5:
continue
ruletype = tokens[0]
protocol = tokens[1]
start = tokens[2]
end = tokens[3]
cidrs = tokens.pop();
ips = cidrs.split(",")
ips.pop()
allow_any = False
if ruletype == 'E':
vmchain = egress_chain_name(vm_name)
direction = "-d"
action = "RETURN"
egressrule = egressrule + 1
else:
vmchain = vm_name
action = "ACCEPT"
direction = "-s"
if '0.0.0.0/0' in ips:
i = ips.index('0.0.0.0/0')
del ips[i]
allow_any = True
range = start + ":" + end
if ips:
if protocol == 'all':
for ip in ips:
execute("iptables -I " + vmchain + " -m state --state NEW " + direction + " " + ip + " -j "+action)
elif protocol != 'icmp':
for ip in ips:
execute("iptables -I " + vmchain + " -p " + protocol + " -m " + protocol + " --dport " + range + " -m state --state NEW " + direction + " " + ip + " -j "+ action)
else:
range = start + "/" + end
if start == "-1":
range = "any"
for ip in ips:
execute("iptables -I " + vmchain + " -p icmp --icmp-type " + range + " " + direction + " " + ip + " -j "+ action)
if allow_any and protocol != 'all':
if protocol != 'icmp':
execute("iptables -I " + vmchain + " -p " + protocol + " -m " + protocol + " --dport " + range + " -m state --state NEW -j "+ action)
else:
range = start + "/" + end
if start == "-1":
range = "any"
execute("iptables -I " + vmchain + " -p icmp --icmp-type " + range + " -j "+action)
egress_vmchain = egress_chain_name(vm_name)
if egressrule == 0 :
iptables = "iptables -A " + egress_vmchain + " -j RETURN"
execute(iptables)
else:
iptables = "iptables -A " + egress_vmchain + " -j DROP"
execute(iptables)
vmchain = vm_name
iptables = "iptables -A " + vmchain + " -j DROP"
execute(iptables)
if write_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno) == False:
return 'false'
return 'true'
except:
logging.debug("Failed to network rule !: " + sys.exc_type)
def getVifs(vmName):
vifs = []
try:
xmlfile = virsh("dumpxml", vmName).stdout
except:
return vifs
dom = xml.dom.minidom.parseString(xmlfile)
for network in dom.getElementsByTagName("interface"):
target = network.getElementsByTagName('target')[0]
nicdev = target.getAttribute("dev").strip()
vifs.append(nicdev)
return vifs
def getVifsForBridge(vmName, brname):
vifs = []
try:
xmlfile = virsh("dumpxml", vmName).stdout
except:
return vifs
dom = xml.dom.minidom.parseString(xmlfile)
for network in dom.getElementsByTagName("interface"):
source = network.getElementsByTagName('source')[0]
bridge = source.getAttribute("bridge").strip()
if bridge == brname:
target = network.getElementsByTagName('target')[0]
nicdev = target.getAttribute("dev").strip()
vifs.append(nicdev)
return list(set(vifs))
def getBridges(vmName):
bridges = []
try:
xmlfile = virsh("dumpxml", vmName).stdout
except:
return bridges
dom = xml.dom.minidom.parseString(xmlfile)
for network in dom.getElementsByTagName("interface"):
for source in network.getElementsByTagName('source'):
bridge = source.getAttribute("bridge").strip()
bridges.append(bridge)
return list(set(bridges))
def getvmId(vmName):
cmd = "virsh list |grep " + vmName + " | awk '{print $1}'"
return bash("-c", cmd).stdout.strip()
def addFWFramework(brname):
try:
cfo = configFileOps("/etc/sysctl.conf")
cfo.addEntry("net.bridge.bridge-nf-call-arptables", "1")
cfo.addEntry("net.bridge.bridge-nf-call-iptables", "1")
cfo.addEntry("net.bridge.bridge-nf-call-ip6tables", "1")
cfo.save()
execute("sysctl -p /etc/sysctl.conf")
except:
logging.debug("failed to turn on bridge netfilter")
return False
brfw = "BF-" + brname
try:
execute("iptables -L " + brfw)
except:
execute("iptables -N " + brfw)
brfwout = brfw + "-OUT"
try:
execute("iptables -L " + brfwout)
except:
execute("iptables -N " + brfwout)
brfwin = brfw + "-IN"
try:
execute("iptables -L " + brfwin)
except:
execute("iptables -N " + brfwin)
try:
refs = execute("iptables -n -L " + brfw + " |grep " + brfw + " | cut -d \( -f2 | awk '{print $1}'").strip()
if refs == "0":
execute("iptables -I FORWARD -i " + brname + " -j DROP")
execute("iptables -I FORWARD -o " + brname + " -j DROP")
execute("iptables -I FORWARD -i " + brname + " -m physdev --physdev-is-bridged -j " + brfw)
execute("iptables -I FORWARD -o " + brname + " -m physdev --physdev-is-bridged -j " + brfw)
phydev = execute("brctl show |grep -w " + brname + " | awk '{print $4}'").strip()
execute("iptables -A " + brfw + " -m state --state RELATED,ESTABLISHED -j ACCEPT")
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-is-in -j " + brfwin)
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-is-out -j " + brfwout)
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-out " + phydev + " -j ACCEPT")
return True
except:
try:
execute("iptables -F " + brfw)
except:
return False
return False
if __name__ == '__main__':
logging.basicConfig(filename="/var/log/cloud/security_group.log", format="%(asctime)s - %(message)s", level=logging.DEBUG)
parser = OptionParser()
parser.add_option("--vmname", dest="vmName")
parser.add_option("--vmip", dest="vmIP")
parser.add_option("--vmid", dest="vmID")
parser.add_option("--vmmac", dest="vmMAC")
parser.add_option("--vif", dest="vif")
parser.add_option("--sig", dest="sig")
parser.add_option("--seq", dest="seq")
parser.add_option("--rules", dest="rules")
parser.add_option("--brname", dest="brname")
parser.add_option("--localbrname", dest="localbrname")
parser.add_option("--dhcpSvr", dest="dhcpSvr")
parser.add_option("--hostIp", dest="hostIp")
parser.add_option("--hostMacAddr", dest="hostMacAddr")
(option, args) = parser.parse_args()
if len(args) == 0:
logging.debug("No command to execute")
sys.exit(1)
cmd = args[0]
if cmd == "can_bridge_firewall":
can_bridge_firewall(args[1])
elif cmd == "default_network_rules":
default_network_rules(option.vmName, option.vmID, option.vmIP, option.vmMAC, option.vif, option.brname)
elif cmd == "destroy_network_rules_for_vm":
destroy_network_rules_for_vm(option.vmName, option.vif)
elif cmd == "default_network_rules_systemvm":
default_network_rules_systemvm(option.vmName, option.localbrname)
elif cmd == "get_rule_logs_for_vms":
get_rule_logs_for_vms()
elif cmd == "add_network_rules":
add_network_rules(option.vmName, option.vmID, option.vmIP, option.sig, option.seq, option.vmMAC, option.rules, option.vif, option.brname)
elif cmd == "cleanup_rules":
cleanup_rules()
elif cmd == "post_default_network_rules":
post_default_network_rules(option.vmName, option.vmID, option.vmIP, option.vmMAC, option.vif, option.brname, option.dhcpSvr, option.hostIp, option.hostMacAddr)
else:
logging.debug("Unknown command: " + cmd)
sys.exit(1)