mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
kvm: Security Group enhancements and refactor old code (#3113)
* security group: Replace deprecated optparse by argparse Starting with Python 2.7 the library optparse has been replaced by argpase. This commit replaces the use of optparse by argparse Signed-off-by: Wido den Hollander <wido@widodh.nl> * security group: Remove LXC support from security_group.py LXC does not work and has been partially removed from CloudStack already Signed-off-by: Wido den Hollander <wido@widodh.nl> * security group: Refactor libvirt code Use a single function which properly throws an Exception when the connection to libvirt fails. Also simplify some logic, make it PEP-8 compatible and remove a unused function from the code. Signed-off-by: Wido den Hollander <wido@widodh.nl> * security group: Raise Exception on execute() failure If the executed command exists with a non-zero exit status we should still return the output to the command, but also raise an Exception. Signed-off-by: Wido den Hollander <wido@widodh.nl> * security group: Use a function to determin the physical device of a bridge We can not safely assume that the first device listed under a bridge is the physical device. With VXLAN isolation a vnet device can be attached to a bridge prior to the vxlanXXXX device being attached. We need to filter out those devices and then fetch the physical device attached to the bridge. In addition use the 'bridge' command instead of 'brctl'. 'bridge' is part of the iproute2 utils just like 'ip' and should be considered as the new default. This command is also available on EL6 and does not break any backwards compat. Signed-off-by: Wido den Hollander <wido@widodh.nl> * security group: --set is deprecated, use --match-set These messages are seen in the KVM Agent log: --set option deprecated, please use --match-set Functionality does not change Signed-off-by: Wido den Hollander <wido@widodh.nl> * security group: PEP-8 and indentation fixes There were a lot of styling problems in the code: - Missing whitespace or exess whitespace - CaMelCaSe function names and variables - 2-space indentation instead of 4 spaces This commit addresses those issues. Signed-off-by: Wido den Hollander <wido@widodh.nl>
This commit is contained in:
parent
1a6eb4b856
commit
ac73e7e671
@ -3491,7 +3491,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
private boolean canBridgeFirewall(final String prvNic) {
|
||||
final Script cmd = new Script(_securityGroupPath, _timeout, s_logger);
|
||||
cmd.add("can_bridge_firewall");
|
||||
cmd.add(prvNic);
|
||||
cmd.add("--privnic", prvNic);
|
||||
final String result = cmd.execute();
|
||||
if (result != null) {
|
||||
return false;
|
||||
|
||||
@ -16,14 +16,12 @@
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import cloud_utils
|
||||
import argparse
|
||||
from subprocess import check_output, CalledProcessError
|
||||
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
|
||||
import libvirt
|
||||
import fcntl
|
||||
@ -35,11 +33,6 @@ from netaddr.core import AddrFormatError
|
||||
logpath = "/var/run/cloud/" # FIXME: Logs should reside in /var/log/cloud
|
||||
lock_file = "/var/lock/cloudstack_security_group.lock"
|
||||
driver = "qemu:///system"
|
||||
cfo = configFileOps("/etc/cloudstack/agent/agent.properties")
|
||||
hyper = cfo.getEntry("hypervisor.type")
|
||||
if hyper == "lxc":
|
||||
driver = "lxc:///"
|
||||
|
||||
lock_handle = None
|
||||
|
||||
|
||||
@ -61,7 +54,8 @@ def execute(cmd):
|
||||
try:
|
||||
return check_output(cmd, shell=True)
|
||||
except CalledProcessError as e:
|
||||
pass
|
||||
logging.exception('Command exited non-zero: %s', cmd)
|
||||
raise
|
||||
|
||||
|
||||
def can_bridge_firewall(privnic):
|
||||
@ -87,22 +81,27 @@ def can_bridge_firewall(privnic):
|
||||
return True
|
||||
|
||||
|
||||
def get_libvirt_connection():
|
||||
conn = libvirt.openReadOnly(driver)
|
||||
if not conn:
|
||||
raise Exception('Failed to open connection to the hypervisor')
|
||||
|
||||
return conn
|
||||
|
||||
|
||||
def virshlist(states):
|
||||
libvirt_states={ 'running' : libvirt.VIR_DOMAIN_RUNNING,
|
||||
'shutoff' : libvirt.VIR_DOMAIN_SHUTOFF,
|
||||
'shutdown' : libvirt.VIR_DOMAIN_SHUTDOWN,
|
||||
'paused' : libvirt.VIR_DOMAIN_PAUSED,
|
||||
'nostate' : libvirt.VIR_DOMAIN_NOSTATE,
|
||||
'blocked' : libvirt.VIR_DOMAIN_BLOCKED,
|
||||
'crashed' : libvirt.VIR_DOMAIN_CRASHED,
|
||||
libvirt_states={ 'running': libvirt.VIR_DOMAIN_RUNNING,
|
||||
'shutoff': libvirt.VIR_DOMAIN_SHUTOFF,
|
||||
'shutdown': libvirt.VIR_DOMAIN_SHUTDOWN,
|
||||
'paused': libvirt.VIR_DOMAIN_PAUSED,
|
||||
'nostate': libvirt.VIR_DOMAIN_NOSTATE,
|
||||
'blocked': libvirt.VIR_DOMAIN_BLOCKED,
|
||||
'crashed': libvirt.VIR_DOMAIN_CRASHED,
|
||||
}
|
||||
|
||||
searchstates = list(libvirt_states[state] for state in states)
|
||||
|
||||
conn = libvirt.openReadOnly(driver)
|
||||
if not conn:
|
||||
print('Failed to open connection to the hypervisor')
|
||||
sys.exit(3)
|
||||
conn = get_libvirt_connection()
|
||||
|
||||
alldomains = map(conn.lookupByID, conn.listDomainsID())
|
||||
alldomains += map(conn.lookupByName, conn.listDefinedDomains())
|
||||
@ -117,48 +116,15 @@ def virshlist(states):
|
||||
return domains
|
||||
|
||||
|
||||
def virshdomstate(domain):
|
||||
libvirt_states={ libvirt.VIR_DOMAIN_RUNNING : 'running',
|
||||
libvirt.VIR_DOMAIN_SHUTOFF : 'shut off',
|
||||
libvirt.VIR_DOMAIN_SHUTDOWN : 'shut down',
|
||||
libvirt.VIR_DOMAIN_PAUSED : 'paused',
|
||||
libvirt.VIR_DOMAIN_NOSTATE : 'no state',
|
||||
libvirt.VIR_DOMAIN_BLOCKED : 'blocked',
|
||||
libvirt.VIR_DOMAIN_CRASHED : 'crashed',
|
||||
}
|
||||
|
||||
conn = libvirt.openReadOnly(driver)
|
||||
if not conn:
|
||||
print('Failed to open connection to the hypervisor')
|
||||
sys.exit(3)
|
||||
|
||||
try:
|
||||
dom = (conn.lookupByName (domain))
|
||||
except libvirt.libvirtError:
|
||||
return None
|
||||
|
||||
state = libvirt_states[dom.info()[0]]
|
||||
conn.close()
|
||||
|
||||
return state
|
||||
|
||||
|
||||
def virshdumpxml(domain):
|
||||
conn = libvirt.openReadOnly(driver)
|
||||
if not conn:
|
||||
print('Failed to open connection to the hypervisor')
|
||||
sys.exit(3)
|
||||
|
||||
try:
|
||||
dom = (conn.lookupByName (domain))
|
||||
conn = get_libvirt_connection()
|
||||
dom = conn.lookupByName(domain)
|
||||
conn.close()
|
||||
return dom.XMLDesc(0)
|
||||
except libvirt.libvirtError:
|
||||
return None
|
||||
|
||||
xml = dom.XMLDesc(0)
|
||||
conn.close()
|
||||
|
||||
return xml
|
||||
|
||||
|
||||
def ipv6_link_local_addr(mac=None):
|
||||
eui64 = re.sub(r'[.:-]', '', mac).lower()
|
||||
@ -182,6 +148,11 @@ def split_ips_by_family(ips):
|
||||
return ip4s, ip6s
|
||||
|
||||
|
||||
def get_bridge_physdev(brname):
|
||||
physdev = execute("bridge -o link show | awk '/master %s / && !/^[0-9]+: vnet/ {print $2}'" % brname)
|
||||
return physdev.strip()
|
||||
|
||||
|
||||
def destroy_network_rules_for_vm(vm_name, vif=None):
|
||||
vmchain = iptables_chain_name(vm_name)
|
||||
vmchain_egress = egress_chain_name(vm_name)
|
||||
@ -229,14 +200,14 @@ def destroy_network_rules_for_vm(vm_name, vif=None):
|
||||
remove_rule_log_for_vm(vm_name)
|
||||
remove_secip_log_for_vm(vm_name)
|
||||
|
||||
if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-'] ]:
|
||||
if 1 in [vm_name.startswith(c) for c in ['r-', 's-', 'v-']]:
|
||||
return True
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def destroy_ebtables_rules(vm_name, vif):
|
||||
eb_vm_chain=ebtables_chain_name(vm_name)
|
||||
eb_vm_chain = ebtables_chain_name(vm_name)
|
||||
delcmd = "ebtables -t nat -L PREROUTING | grep " + eb_vm_chain
|
||||
delcmds = []
|
||||
try:
|
||||
@ -319,8 +290,8 @@ def default_ebtables_rules(vm_name, vm_ip, vm_mac, vif):
|
||||
|
||||
|
||||
def default_network_rules_systemvm(vm_name, localbrname):
|
||||
bridges = getBridges(vm_name)
|
||||
domid = getvmId(vm_name)
|
||||
bridges = get_bridges(vm_name)
|
||||
domid = get_vm_id(vm_name)
|
||||
vmchain = iptables_chain_name(vm_name)
|
||||
|
||||
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
|
||||
@ -332,10 +303,10 @@ def default_network_rules_systemvm(vm_name, localbrname):
|
||||
|
||||
for bridge in bridges:
|
||||
if bridge != localbrname:
|
||||
if not addFWFramework(bridge):
|
||||
if not add_fw_framework(bridge):
|
||||
return False
|
||||
brfw = getBrfw(bridge)
|
||||
vifs = getVifsForBridge(vm_name, bridge)
|
||||
brfw = get_br_fw(bridge)
|
||||
vifs = get_vifs_for_bridge(vm_name, bridge)
|
||||
for vif in vifs:
|
||||
try:
|
||||
execute("iptables -A " + brfw + "-OUT" + " -m physdev --physdev-is-bridged --physdev-out " + vif + " -j " + vmchain)
|
||||
@ -417,8 +388,6 @@ def network_rules_vmSecondaryIp(vm_name, ip_secondary, action):
|
||||
logging.debug("vmName = "+ vm_name)
|
||||
logging.debug("action = "+ action)
|
||||
|
||||
domid = getvmId(vm_name)
|
||||
|
||||
vmchain = vm_name
|
||||
vmchain6 = vmchain + '-6'
|
||||
|
||||
@ -455,12 +424,12 @@ def ebtables_rules_vmip (vmname, ips, action):
|
||||
|
||||
|
||||
def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, sec_ips):
|
||||
if not addFWFramework(brname):
|
||||
if not add_fw_framework(brname):
|
||||
return False
|
||||
|
||||
vmName = vm_name
|
||||
brfw = getBrfw(brname)
|
||||
domID = getvmId(vm_name)
|
||||
brfw = get_br_fw(brname)
|
||||
domID = get_vm_id(vm_name)
|
||||
delete_rules_for_vm_in_bridge_firewall_chain(vmName)
|
||||
vmchain = iptables_chain_name(vm_name)
|
||||
vmchain_egress = egress_chain_name(vm_name)
|
||||
@ -486,13 +455,13 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
|
||||
|
||||
#create ipset and add vm ips to that ip set
|
||||
if not create_ipset_forvm(vmipsetName):
|
||||
logging.debug(" failed to create ipset for rule " + str(tokens))
|
||||
return False
|
||||
logging.debug("failed to create ipset for rule %s", vmipsetName)
|
||||
return False
|
||||
|
||||
#add primary nic ip to ipset
|
||||
if not add_to_ipset(vmipsetName, [vm_ip], action ):
|
||||
logging.debug(" failed to add vm " + vm_ip + " ip to set ")
|
||||
return False
|
||||
logging.debug("failed to add vm " + vm_ip + " ip to set ")
|
||||
return False
|
||||
|
||||
#add secodnary nic ips to ipset
|
||||
secIpSet = "1"
|
||||
@ -510,7 +479,7 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
|
||||
|
||||
add_to_ipset(vmipsetName, ip4s, action)
|
||||
|
||||
if write_secip_log_for_vm(vm_name, sec_ips, vm_id) == False:
|
||||
if not write_secip_log_for_vm(vm_name, sec_ips, vm_id):
|
||||
logging.debug("Failed to log default network rules, ignoring")
|
||||
|
||||
try:
|
||||
@ -523,10 +492,10 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
|
||||
|
||||
#don't let vm spoof its ip address
|
||||
if vm_ip:
|
||||
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set ! --set " + vmipsetName + " src -j DROP")
|
||||
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set --set " + vmipsetName + " src -p udp --dport 53 -j RETURN ")
|
||||
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set --set " + vmipsetName + " src -p tcp --dport 53 -j RETURN ")
|
||||
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set --set " + vmipsetName + " src -j " + vmchain_egress)
|
||||
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set ! --match-set " + vmipsetName + " src -j DROP")
|
||||
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set --match-set " + vmipsetName + " src -p udp --dport 53 -j RETURN ")
|
||||
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set --match-set " + vmipsetName + " src -p tcp --dport 53 -j RETURN ")
|
||||
execute("iptables -A " + vmchain_default + " -m physdev --physdev-is-bridged --physdev-in " + vif + " -m set --match-set " + vmipsetName + " src -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:
|
||||
@ -542,8 +511,8 @@ def default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vm_mac, vif, brname, se
|
||||
logging.debug("Failed to log default network rules, ignoring")
|
||||
|
||||
if not create_ipset_forvm(vmipsetName6, family='inet6', type='hash:net'):
|
||||
logging.debug(" failed to create ivp6 ipset for rule " + str(tokens))
|
||||
return False
|
||||
logging.debug(" failed to create ivp6 ipset for rule " + str(tokens))
|
||||
return False
|
||||
|
||||
vm_ip6_addr = [ipv6_link_local]
|
||||
try:
|
||||
@ -622,7 +591,7 @@ def post_default_network_rules(vm_name, vm_id, vm_ip, vm_mac, vif, brname, dhcpS
|
||||
iptables_vmchain=iptables_chain_name(vm_name)
|
||||
vmchain_in = iptables_vmchain + "-in"
|
||||
vmchain_out = iptables_vmchain + "-out"
|
||||
domID = getvmId(vm_name)
|
||||
domID = get_vm_id(vm_name)
|
||||
try:
|
||||
execute("iptables -I " + vmchain_default + " 4 -m physdev --physdev-is-bridged --physdev-in " + vif + " --source " + vm_ip + " -j ACCEPT")
|
||||
except:
|
||||
@ -705,7 +674,7 @@ def get_rule_log_for_vm(vmName):
|
||||
|
||||
|
||||
def check_domid_changed(vmName):
|
||||
curr_domid = getvmId(vmName)
|
||||
curr_domid = get_vm_id(vmName)
|
||||
if (curr_domid is None) or (not curr_domid.isdigit()):
|
||||
curr_domid = '-1'
|
||||
|
||||
@ -754,13 +723,13 @@ def network_rules_for_rebooted_vm(vmName):
|
||||
vmchain = iptables_chain_name(vm_name)
|
||||
vmchain_default = '-'.join(vmchain.split('-')[:-1]) + "-def"
|
||||
|
||||
vifs = getVifs(vmName)
|
||||
vifs = get_vifs(vmName)
|
||||
logging.debug(vifs, brName)
|
||||
for v in vifs:
|
||||
execute("iptables -A " + getBrfw(brName) + "-IN " + " -m physdev --physdev-is-bridged --physdev-in " + v + " -j "+ vmchain_default)
|
||||
execute("iptables -A " + getBrfw(brName) + "-OUT " + " -m physdev --physdev-is-bridged --physdev-out " + v + " -j "+ vmchain_default)
|
||||
execute("ip6tables -A " + getBrfw(brName) + "-IN " + " -m physdev --physdev-is-bridged --physdev-in " + v + " -j " + vmchain_default)
|
||||
execute("ip6tables -A " + getBrfw(brName) + "-OUT " + " -m physdev --physdev-is-bridged --physdev-out " + v + " -j " + vmchain_default)
|
||||
execute("iptables -A " + get_br_fw(brName) + "-IN " + " -m physdev --physdev-is-bridged --physdev-in " + v + " -j " + vmchain_default)
|
||||
execute("iptables -A " + get_br_fw(brName) + "-OUT " + " -m physdev --physdev-is-bridged --physdev-out " + v + " -j " + vmchain_default)
|
||||
execute("ip6tables -A " + get_br_fw(brName) + "-IN " + " -m physdev --physdev-is-bridged --physdev-in " + v + " -j " + vmchain_default)
|
||||
execute("ip6tables -A " + get_br_fw(brName) + "-OUT " + " -m physdev --physdev-is-bridged --physdev-out " + v + " -j " + vmchain_default)
|
||||
|
||||
#change antispoof rule in vmchain
|
||||
try:
|
||||
@ -787,14 +756,14 @@ def network_rules_for_rebooted_vm(vmName):
|
||||
|
||||
|
||||
def get_rule_logs_for_vms():
|
||||
state=['running']
|
||||
state = ['running']
|
||||
vms = virshlist(state)
|
||||
|
||||
result = []
|
||||
try:
|
||||
for name in vms:
|
||||
name = name.rstrip()
|
||||
if 1 not in [ name.startswith(c) for c in ['r-', 's-', 'v-', 'i-'] ]:
|
||||
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-'):
|
||||
@ -811,7 +780,7 @@ def cleanup_rules_for_dead_vms():
|
||||
|
||||
|
||||
def cleanup_bridge(bridge):
|
||||
bridge_name = getBrfw(bridge)
|
||||
bridge_name = get_br_fw(bridge)
|
||||
logging.debug("Cleaning old bridge chains: " + bridge_name)
|
||||
if not bridge_name:
|
||||
return True
|
||||
@ -840,7 +809,7 @@ def cleanup_bridge(bridge):
|
||||
|
||||
def cleanup_rules():
|
||||
try:
|
||||
states=['running','paused']
|
||||
states = ['running', 'paused']
|
||||
vmsInHost = virshlist(states)
|
||||
|
||||
logging.debug(" Vms on the host : %s ", vmsInHost)
|
||||
@ -854,11 +823,11 @@ def cleanup_rules():
|
||||
for chain in chains:
|
||||
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]:
|
||||
vm_name = chain
|
||||
vmpresent=False
|
||||
vmpresent = False
|
||||
|
||||
for vm in vmsInHost:
|
||||
if vm_name in vm:
|
||||
vmpresent=True
|
||||
vmpresent = True
|
||||
break
|
||||
|
||||
if vmpresent is False:
|
||||
@ -873,12 +842,12 @@ def cleanup_rules():
|
||||
logging.debug(" ebtables chains in the host: %s ", chains)
|
||||
|
||||
for chain in filter(None, chains):
|
||||
if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]:
|
||||
if 1 in [chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-']]:
|
||||
vm_name = chain
|
||||
vmpresent=False
|
||||
vmpresent = False
|
||||
for vm in vmsInHost:
|
||||
if vm_name in vm:
|
||||
vmpresent=True
|
||||
vmpresent = True
|
||||
break
|
||||
|
||||
if vmpresent is False:
|
||||
@ -980,144 +949,144 @@ def egress_chain_name(vm_name):
|
||||
|
||||
|
||||
def parse_network_rules(rules):
|
||||
ret = []
|
||||
ret = []
|
||||
|
||||
if rules is None or len(rules) == 0:
|
||||
return ret
|
||||
|
||||
lines = rules.split('NEXT;')[:-1]
|
||||
for line in lines:
|
||||
tokens = line.split(';', 3)
|
||||
if len(tokens) != 4:
|
||||
continue
|
||||
|
||||
ruletype, protocol = tokens[0].split(':')
|
||||
start = int(tokens[1])
|
||||
end = int(tokens[2])
|
||||
cidrs = tokens.pop()
|
||||
|
||||
ipv4 = []
|
||||
ipv6 = []
|
||||
for ip in cidrs.split(","):
|
||||
try:
|
||||
network = IPNetwork(ip)
|
||||
if network.version == 4:
|
||||
ipv4.append(ip)
|
||||
else:
|
||||
ipv6.append(ip)
|
||||
except:
|
||||
pass
|
||||
|
||||
ret.append({'ipv4': ipv4, 'ipv6': ipv6, 'ruletype': ruletype,
|
||||
'start': start, 'end': end, 'protocol': protocol})
|
||||
|
||||
if rules is None or len(rules) == 0:
|
||||
return ret
|
||||
|
||||
lines = rules.split('NEXT;')[:-1]
|
||||
for line in lines:
|
||||
tokens = line.split(';', 3)
|
||||
if len(tokens) != 4:
|
||||
continue
|
||||
|
||||
ruletype, protocol = tokens[0].split(':')
|
||||
start = int(tokens[1])
|
||||
end = int(tokens[2])
|
||||
cidrs = tokens.pop()
|
||||
|
||||
ipv4 = []
|
||||
ipv6 = []
|
||||
for ip in cidrs.split(","):
|
||||
try:
|
||||
network = IPNetwork(ip)
|
||||
if network.version == 4:
|
||||
ipv4.append(ip)
|
||||
else:
|
||||
ipv6.append(ip)
|
||||
except:
|
||||
pass
|
||||
|
||||
ret.append({'ipv4': ipv4, 'ipv6': ipv6, 'ruletype': ruletype,
|
||||
'start': start, 'end': end, 'protocol': protocol})
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def add_network_rules(vm_name, vm_id, vm_ip, vm_ip6, signature, seqno, vmMac, rules, vif, brname, sec_ips):
|
||||
try:
|
||||
vmName = vm_name
|
||||
domId = getvmId(vmName)
|
||||
|
||||
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, vm_ip6, vmMac, vif, brname, sec_ips)
|
||||
|
||||
logging.debug(" programming network rules for IP: " + vm_ip + " vmname=" + vm_name)
|
||||
|
||||
egress_chain_name(vm_name)
|
||||
vmchain = iptables_chain_name(vm_name)
|
||||
egress_vmchain = egress_chain_name(vm_name)
|
||||
|
||||
try:
|
||||
for chain in [vmchain, egress_vmchain]:
|
||||
execute('iptables -F ' + chain)
|
||||
execute('ip6tables -F ' + chain)
|
||||
except:
|
||||
logging.debug("Error flushing iptables rules for " + vm_name + ". Presuming firewall rules deleted, re-initializing." )
|
||||
default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vmMac, vif, brname, sec_ips)
|
||||
vmName = vm_name
|
||||
domId = get_vm_id(vmName)
|
||||
|
||||
egressrule_v4 = 0
|
||||
egressrule_v6 = 0
|
||||
changes = check_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno)
|
||||
|
||||
for rule in parse_network_rules(rules):
|
||||
start = rule['start']
|
||||
end = rule['end']
|
||||
protocol = rule['protocol']
|
||||
if not 1 in changes:
|
||||
logging.debug("Rules already programmed for vm " + vm_name)
|
||||
return True
|
||||
|
||||
if rule['ruletype'] == 'E':
|
||||
vmchain = egress_vmchain
|
||||
direction = "-d"
|
||||
action = "RETURN"
|
||||
if rule['ipv4']:
|
||||
egressrule_v4 =+ 1
|
||||
if changes[0] or changes[1] or changes[2] or changes[3]:
|
||||
default_network_rules(vmName, vm_id, vm_ip, vm_ip6, vmMac, vif, brname, sec_ips)
|
||||
|
||||
if rule['ipv6']:
|
||||
egressrule_v6 +=1
|
||||
logging.debug("programming network rules for IP: " + vm_ip + " vmname=%s", vm_name)
|
||||
|
||||
else:
|
||||
vmchain = vm_name
|
||||
action = "ACCEPT"
|
||||
direction = "-s"
|
||||
egress_chain_name(vm_name)
|
||||
vmchain = iptables_chain_name(vm_name)
|
||||
egress_vmchain = egress_chain_name(vm_name)
|
||||
|
||||
range = str(start) + ':' + str(end)
|
||||
if 'icmp' == protocol:
|
||||
range = str(start) + '/' + str(end)
|
||||
if start == -1:
|
||||
range = 'any'
|
||||
try:
|
||||
for chain in [vmchain, egress_vmchain]:
|
||||
execute('iptables -F ' + chain)
|
||||
execute('ip6tables -F ' + chain)
|
||||
except:
|
||||
logging.debug("Error flushing iptables rules for " + vm_name + ". Presuming firewall rules deleted, re-initializing." )
|
||||
default_network_rules(vm_name, vm_id, vm_ip, vm_ip6, vmMac, vif, brname, sec_ips)
|
||||
|
||||
egressrule_v4 = 0
|
||||
egressrule_v6 = 0
|
||||
|
||||
for rule in parse_network_rules(rules):
|
||||
start = rule['start']
|
||||
end = rule['end']
|
||||
protocol = rule['protocol']
|
||||
|
||||
if rule['ruletype'] == 'E':
|
||||
vmchain = egress_vmchain
|
||||
direction = "-d"
|
||||
action = "RETURN"
|
||||
if rule['ipv4']:
|
||||
egressrule_v4 =+ 1
|
||||
|
||||
if rule['ipv6']:
|
||||
egressrule_v6 +=1
|
||||
|
||||
for ip in rule['ipv4']:
|
||||
if protocol == 'all':
|
||||
execute('iptables -I ' + vmchain + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
|
||||
elif protocol != 'icmp':
|
||||
execute('iptables -I ' + vmchain + ' -p ' + protocol + ' -m ' + protocol + ' --dport ' + range + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
|
||||
else:
|
||||
execute('iptables -I ' + vmchain + ' -p icmp --icmp-type ' + range + ' ' + direction + ' ' + ip + ' -j ' + action)
|
||||
vmchain = vm_name
|
||||
action = "ACCEPT"
|
||||
direction = "-s"
|
||||
|
||||
for ip in rule['ipv6']:
|
||||
if protocol == 'all':
|
||||
execute('ip6tables -I ' + vmchain + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
|
||||
elif 'icmp' != protocol:
|
||||
execute('ip6tables -I ' + vmchain + ' -p ' + protocol + ' -m ' + protocol + ' --dport ' + range + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
|
||||
else:
|
||||
# ip6tables does not allow '--icmpv6-type any', allowing all ICMPv6 is done by not allowing a specific type
|
||||
if range == 'any':
|
||||
execute('ip6tables -I ' + vmchain + ' -p icmpv6 ' + direction + ' ' + ip + ' -j ' + action)
|
||||
range = str(start) + ':' + str(end)
|
||||
if 'icmp' == protocol:
|
||||
range = str(start) + '/' + str(end)
|
||||
if start == -1:
|
||||
range = 'any'
|
||||
|
||||
for ip in rule['ipv4']:
|
||||
if protocol == 'all':
|
||||
execute('iptables -I ' + vmchain + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
|
||||
elif protocol != 'icmp':
|
||||
execute('iptables -I ' + vmchain + ' -p ' + protocol + ' -m ' + protocol + ' --dport ' + range + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
|
||||
else:
|
||||
execute('ip6tables -I ' + vmchain + ' -p icmpv6 --icmpv6-type ' + range + ' ' + direction + ' ' + ip + ' -j ' + action)
|
||||
execute('iptables -I ' + vmchain + ' -p icmp --icmp-type ' + range + ' ' + direction + ' ' + ip + ' -j ' + action)
|
||||
|
||||
egress_vmchain = egress_chain_name(vm_name)
|
||||
if egressrule_v4 == 0 :
|
||||
execute('iptables -A ' + egress_vmchain + ' -j RETURN')
|
||||
else:
|
||||
execute('iptables -A ' + egress_vmchain + ' -j DROP')
|
||||
for ip in rule['ipv6']:
|
||||
if protocol == 'all':
|
||||
execute('ip6tables -I ' + vmchain + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
|
||||
elif 'icmp' != protocol:
|
||||
execute('ip6tables -I ' + vmchain + ' -p ' + protocol + ' -m ' + protocol + ' --dport ' + range + ' -m state --state NEW ' + direction + ' ' + ip + ' -j ' + action)
|
||||
else:
|
||||
# ip6tables does not allow '--icmpv6-type any', allowing all ICMPv6 is done by not allowing a specific type
|
||||
if range == 'any':
|
||||
execute('ip6tables -I ' + vmchain + ' -p icmpv6 ' + direction + ' ' + ip + ' -j ' + action)
|
||||
else:
|
||||
execute('ip6tables -I ' + vmchain + ' -p icmpv6 --icmpv6-type ' + range + ' ' + direction + ' ' + ip + ' -j ' + action)
|
||||
|
||||
if egressrule_v6 == 0 :
|
||||
execute('ip6tables -A ' + egress_vmchain + ' -j RETURN')
|
||||
else:
|
||||
execute('ip6tables -A ' + egress_vmchain + ' -j DROP')
|
||||
egress_vmchain = egress_chain_name(vm_name)
|
||||
if egressrule_v4 == 0 :
|
||||
execute('iptables -A ' + egress_vmchain + ' -j RETURN')
|
||||
else:
|
||||
execute('iptables -A ' + egress_vmchain + ' -j DROP')
|
||||
|
||||
vmchain = iptables_chain_name(vm_name)
|
||||
if egressrule_v6 == 0 :
|
||||
execute('ip6tables -A ' + egress_vmchain + ' -j RETURN')
|
||||
else:
|
||||
execute('ip6tables -A ' + egress_vmchain + ' -j DROP')
|
||||
|
||||
execute('iptables -A ' + vmchain + ' -j DROP')
|
||||
execute('ip6tables -A ' + vmchain + ' -j DROP')
|
||||
vmchain = iptables_chain_name(vm_name)
|
||||
|
||||
if not write_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno):
|
||||
return False
|
||||
execute('iptables -A ' + vmchain + ' -j DROP')
|
||||
execute('ip6tables -A ' + vmchain + ' -j DROP')
|
||||
|
||||
return True
|
||||
except:
|
||||
logging.exception("Failed to network rule !")
|
||||
if not write_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno):
|
||||
return False
|
||||
|
||||
return True
|
||||
except:
|
||||
logging.exception("Failed to network rule !")
|
||||
|
||||
|
||||
def getVifs(vmName):
|
||||
def get_vifs(vm_name):
|
||||
vifs = []
|
||||
xmlfile = virshdumpxml(vmName)
|
||||
xmlfile = virshdumpxml(vm_name)
|
||||
if not xmlfile:
|
||||
return vifs
|
||||
|
||||
@ -1129,9 +1098,9 @@ def getVifs(vmName):
|
||||
return vifs
|
||||
|
||||
|
||||
def getVifsForBridge(vmName, brname):
|
||||
def get_vifs_for_bridge(vm_name, brname):
|
||||
vifs = []
|
||||
xmlfile = virshdumpxml(vmName)
|
||||
xmlfile = virshdumpxml(vm_name)
|
||||
if not xmlfile:
|
||||
return vifs
|
||||
|
||||
@ -1146,9 +1115,9 @@ def getVifsForBridge(vmName, brname):
|
||||
return list(set(vifs))
|
||||
|
||||
|
||||
def getBridges(vmName):
|
||||
def get_bridges(vm_name):
|
||||
bridges = []
|
||||
xmlfile = virshdumpxml(vmName)
|
||||
xmlfile = virshdumpxml(vm_name)
|
||||
if not xmlfile:
|
||||
return bridges
|
||||
|
||||
@ -1160,15 +1129,10 @@ def getBridges(vmName):
|
||||
return list(set(bridges))
|
||||
|
||||
|
||||
def getvmId(vmName):
|
||||
|
||||
conn = libvirt.openReadOnly(driver)
|
||||
if not conn:
|
||||
print('Failed to open connection to the hypervisor')
|
||||
sys.exit(3)
|
||||
|
||||
def get_vm_id(vm_name):
|
||||
conn = get_libvirt_connection()
|
||||
try:
|
||||
dom = (conn.lookupByName (vmName))
|
||||
dom = (conn.lookupByName (vm_name))
|
||||
except libvirt.libvirtError:
|
||||
return None
|
||||
|
||||
@ -1180,7 +1144,7 @@ def getvmId(vmName):
|
||||
return res
|
||||
|
||||
|
||||
def getBrfw(brname):
|
||||
def get_br_fw(brname):
|
||||
cmd = "iptables-save |grep physdev-is-bridged |grep FORWARD |grep BF |grep '\-o' | grep -w " + brname + "|awk '{print $9}' | head -1"
|
||||
brfwname = execute(cmd).strip()
|
||||
if not brfwname:
|
||||
@ -1188,7 +1152,7 @@ def getBrfw(brname):
|
||||
return brfwname
|
||||
|
||||
|
||||
def addFWFramework(brname):
|
||||
def add_fw_framework(brname):
|
||||
try:
|
||||
execute("sysctl -w net.bridge.bridge-nf-call-arptables=1")
|
||||
execute("sysctl -w net.bridge.bridge-nf-call-iptables=1")
|
||||
@ -1196,7 +1160,7 @@ def addFWFramework(brname):
|
||||
except:
|
||||
logging.warn("failed to turn on bridge netfilter")
|
||||
|
||||
brfw = getBrfw(brname)
|
||||
brfw = get_br_fw(brname)
|
||||
try:
|
||||
execute("iptables -L " + brfw)
|
||||
except:
|
||||
@ -1231,6 +1195,8 @@ def addFWFramework(brname):
|
||||
except:
|
||||
execute('ip6tables -N ' + brfwin)
|
||||
|
||||
physdev = get_bridge_physdev(brname)
|
||||
|
||||
try:
|
||||
refs = int(execute("""iptables -n -L %s | awk '/%s(.*)references/ {gsub(/\(/, "") ;print $3}'""" % (brfw,brfw)).strip())
|
||||
refs6 = int(execute("""ip6tables -n -L %s | awk '/%s(.*)references/ {gsub(/\(/, "") ;print $3}'""" % (brfw,brfw)).strip())
|
||||
@ -1240,22 +1206,20 @@ def addFWFramework(brname):
|
||||
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 | awk '/^%s[ \t]/ {print $4}'" % brname ).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")
|
||||
execute("iptables -A " + brfw + " -m physdev --physdev-is-bridged --physdev-out " + physdev + " -j ACCEPT")
|
||||
|
||||
if refs6 == 0:
|
||||
execute('ip6tables -I FORWARD -i ' + brname + ' -j DROP')
|
||||
execute('ip6tables -I FORWARD -o ' + brname + ' -j DROP')
|
||||
execute('ip6tables -I FORWARD -i ' + brname + ' -m physdev --physdev-is-bridged -j ' + brfw)
|
||||
execute('ip6tables -I FORWARD -o ' + brname + ' -m physdev --physdev-is-bridged -j ' + brfw)
|
||||
phydev = execute("brctl show | awk '/^%s[ \t]/ {print $4}'" % brname ).strip()
|
||||
execute('ip6tables -A ' + brfw + ' -m state --state RELATED,ESTABLISHED -j ACCEPT')
|
||||
execute('ip6tables -A ' + brfw + ' -m physdev --physdev-is-bridged --physdev-is-in -j ' + brfwin)
|
||||
execute('ip6tables -A ' + brfw + ' -m physdev --physdev-is-bridged --physdev-is-out -j ' + brfwout)
|
||||
execute('ip6tables -A ' + brfw + ' -m physdev --physdev-is-bridged --physdev-out ' + phydev + ' -j ACCEPT')
|
||||
execute('ip6tables -A ' + brfw + ' -m physdev --physdev-is-bridged --physdev-out ' + physdev + ' -j ACCEPT')
|
||||
|
||||
return True
|
||||
except:
|
||||
@ -1269,29 +1233,28 @@ def addFWFramework(brname):
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(filename="/var/log/cloudstack/agent/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("--vmip6", dest="vmIP6")
|
||||
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")
|
||||
parser.add_option("--nicsecips", dest="nicSecIps")
|
||||
parser.add_option("--action", dest="action")
|
||||
(option, args) = parser.parse_args()
|
||||
if len(args) == 0:
|
||||
logging.debug("No command to execute")
|
||||
sys.exit(1)
|
||||
cmd = args[0]
|
||||
logging.debug("Executing command: " + str(cmd))
|
||||
parser = argparse.ArgumentParser(description='Apache CloudStack Security Groups')
|
||||
parser.add_argument("command")
|
||||
parser.add_argument("--vmname", dest="vmName")
|
||||
parser.add_argument("--vmip", dest="vmIP")
|
||||
parser.add_argument("--vmip6", dest="vmIP6")
|
||||
parser.add_argument("--vmid", dest="vmID")
|
||||
parser.add_argument("--vmmac", dest="vmMAC")
|
||||
parser.add_argument("--vif", dest="vif")
|
||||
parser.add_argument("--sig", dest="sig")
|
||||
parser.add_argument("--seq", dest="seq")
|
||||
parser.add_argument("--rules", dest="rules")
|
||||
parser.add_argument("--brname", dest="brname")
|
||||
parser.add_argument("--localbrname", dest="localbrname")
|
||||
parser.add_argument("--dhcpSvr", dest="dhcpSvr")
|
||||
parser.add_argument("--hostIp", dest="hostIp")
|
||||
parser.add_argument("--hostMacAddr", dest="hostMacAddr")
|
||||
parser.add_argument("--nicsecips", dest="nicSecIps")
|
||||
parser.add_argument("--action", dest="action")
|
||||
parser.add_argument("--privnic", dest="privnic")
|
||||
args = parser.parse_args()
|
||||
cmd = args.command
|
||||
logging.debug("Executing command: %s", cmd)
|
||||
|
||||
for i in range(0, 30):
|
||||
if obtain_file_lock(lock_file) is False:
|
||||
@ -1301,23 +1264,23 @@ if __name__ == '__main__':
|
||||
break
|
||||
|
||||
if cmd == "can_bridge_firewall":
|
||||
can_bridge_firewall(args[1])
|
||||
can_bridge_firewall(args.privnic)
|
||||
elif cmd == "default_network_rules":
|
||||
default_network_rules(option.vmName, option.vmID, option.vmIP, option.vmIP6, option.vmMAC, option.vif, option.brname, option.nicSecIps)
|
||||
default_network_rules(args.vmName, args.vmID, args.vmIP, args.vmIP6, args.vmMAC, args.vif, args.brname, args.nicSecIps)
|
||||
elif cmd == "destroy_network_rules_for_vm":
|
||||
destroy_network_rules_for_vm(option.vmName, option.vif)
|
||||
destroy_network_rules_for_vm(args.vmName, args.vif)
|
||||
elif cmd == "default_network_rules_systemvm":
|
||||
default_network_rules_systemvm(option.vmName, option.localbrname)
|
||||
default_network_rules_systemvm(args.vmName, args.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.vmIP6, option.sig, option.seq, option.vmMAC, option.rules, option.vif, option.brname, option.nicSecIps)
|
||||
add_network_rules(args.vmName, args.vmID, args.vmIP, args.vmIP6, args.sig, args.seq, args.vmMAC, args.rules, args.vif, args.brname, args.nicSecIps)
|
||||
elif cmd == "network_rules_vmSecondaryIp":
|
||||
network_rules_vmSecondaryIp(option.vmName, option.nicSecIps, option.action)
|
||||
network_rules_vmSecondaryIp(args.vmName, args.nicSecIps, args.action)
|
||||
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)
|
||||
post_default_network_rules(args.vmName, args.vmID, args.vmIP, args.vmMAC, args.vif, args.brname, args.dhcpSvr, args.hostIp, args.hostMacAddr)
|
||||
else:
|
||||
logging.debug("Unknown command: " + cmd)
|
||||
sys.exit(1)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user