Enable support for security group logging
Add support to enabling logging of security groups for OpenStack Queens or later; this feature is enabled via the neutron-api charm, with local charm configuration options to allow control of rate and burst limits and to set a local log output directory if require (allowing log data to be written to a separate partition for example). The feature is only compatible with the openvswitch firewall driver and will not be enabled if this configuration option is not set. Basic deployment tests changes is included here since nova-cloud-controller unit and relation was missing before, and it leads to CI constantly failing. Corresponding charm-helpers change: https://github.com/juju/charm-helpers/pull/228 Change-Id: Id6ed09f714981e87838186d51a4f5e693bedb1d3 Closes-Bug: #1787397 Depends-On: https://review.openstack.org/602355
This commit is contained in:
parent
d0f0dbf577
commit
40701500b5
1
.gitignore
vendored
1
.gitignore
vendored
@ -12,3 +12,4 @@ func-results.json
|
||||
.stestr
|
||||
__pycache__
|
||||
joined-string
|
||||
.idea
|
||||
|
26
config.yaml
26
config.yaml
@ -250,7 +250,31 @@ options:
|
||||
configured will be used.
|
||||
ipfix-target:
|
||||
type: string
|
||||
default:
|
||||
default:
|
||||
description: |
|
||||
IPFIX target wit the format "IP_Address:Port". This will enable IPFIX
|
||||
exporting on all OVS bridges to the target, including br-int and br-ext.
|
||||
security-group-log-output-base:
|
||||
type: string
|
||||
default:
|
||||
description: |
|
||||
This option allows setting a path for Network Security Group logs.
|
||||
A valid file system path must be provided. If this option is not
|
||||
provided Neutron will use syslog as a destination.
|
||||
(Available from Queens)
|
||||
security-group-log-rate-limit:
|
||||
type: int
|
||||
default:
|
||||
description: |
|
||||
Log entries are queued for writing to a log file when a packet rate
|
||||
exceeds the limit set by this option.
|
||||
Possible values: null (no rate limitation), integer values greater than 100.
|
||||
WARNING: Should be NOT LESS than 100, if set
|
||||
(or, if null, logging will log unlimited.)
|
||||
security-group-log-burst-limit:
|
||||
type: int
|
||||
default: 25
|
||||
description: |
|
||||
This option sets the maximum queue size for log entries.
|
||||
Can be used to avoid excessive memory consumption.
|
||||
WARNING: Should be NOT LESS than 25.
|
@ -1534,10 +1534,15 @@ class NeutronAPIContext(OSContextGenerator):
|
||||
if 'l2-population' in rdata:
|
||||
ctxt.update(self.get_neutron_options(rdata))
|
||||
|
||||
extension_drivers = []
|
||||
|
||||
if ctxt['enable_qos']:
|
||||
ctxt['extension_drivers'] = 'qos'
|
||||
else:
|
||||
ctxt['extension_drivers'] = ''
|
||||
extension_drivers.append('qos')
|
||||
|
||||
if ctxt['enable_nsg_logging']:
|
||||
extension_drivers.append('log')
|
||||
|
||||
ctxt['extension_drivers'] = ','.join(extension_drivers)
|
||||
|
||||
return ctxt
|
||||
|
||||
|
@ -51,7 +51,7 @@ OPENVSWITCH = 'openvswitch'
|
||||
VALID_FIREWALL_DRIVERS = (IPTABLES_HYBRID, OPENVSWITCH)
|
||||
|
||||
|
||||
def _get_firewall_driver():
|
||||
def _get_firewall_driver(ovs_ctxt):
|
||||
'''
|
||||
Determine the firewall driver to use based on configuration,
|
||||
OpenStack and Ubuntu releases.
|
||||
@ -62,6 +62,12 @@ def _get_firewall_driver():
|
||||
release = lsb_release()['DISTRIB_CODENAME']
|
||||
if driver not in VALID_FIREWALL_DRIVERS:
|
||||
return IPTABLES_HYBRID
|
||||
|
||||
if driver == IPTABLES_HYBRID and ovs_ctxt['enable_nsg_logging']:
|
||||
msg = "NSG logging can not be enabled - need to set " \
|
||||
"firewall driver to 'openvswitch' explicitly"
|
||||
log(msg, "WARN")
|
||||
|
||||
if (driver == OPENVSWITCH and
|
||||
CompareHostReleases(release) < 'xenial'):
|
||||
# NOTE(jamespage): Switch back to iptables_hybrid for
|
||||
@ -69,9 +75,37 @@ def _get_firewall_driver():
|
||||
# to requirements for Linux >= 4.4 and
|
||||
# Open vSwitch >= 2.5
|
||||
return IPTABLES_HYBRID
|
||||
|
||||
return driver
|
||||
|
||||
|
||||
def get_nsg_log_path(desired_nsg_log_path):
|
||||
if not desired_nsg_log_path:
|
||||
# None means "we need to use syslog" - no need
|
||||
# to check anything on filesystem
|
||||
return None
|
||||
|
||||
dst_dir, _ = os.path.split(desired_nsg_log_path)
|
||||
path_exists = os.path.exists(dst_dir)
|
||||
if not path_exists:
|
||||
log(
|
||||
"Desired NSG log directory {} not exists! "
|
||||
"falling back to syslog".format(dst_dir),
|
||||
"WARN"
|
||||
)
|
||||
return None
|
||||
|
||||
if path_exists and os.path.isdir(desired_nsg_log_path):
|
||||
log(
|
||||
"Desired NSG log path {} should be file, not directory! "
|
||||
"falling back to syslog".format(desired_nsg_log_path),
|
||||
"WARN"
|
||||
)
|
||||
return None
|
||||
|
||||
return desired_nsg_log_path
|
||||
|
||||
|
||||
class OVSPluginContext(context.NeutronContext):
|
||||
interfaces = []
|
||||
|
||||
@ -132,7 +166,6 @@ class OVSPluginContext(context.NeutronContext):
|
||||
ovs_ctxt['use_syslog'] = conf['use-syslog']
|
||||
ovs_ctxt['verbose'] = conf['verbose']
|
||||
ovs_ctxt['debug'] = conf['debug']
|
||||
|
||||
cmp_release = CompareOpenStackReleases(
|
||||
os_release('neutron-common', base='icehouse'))
|
||||
if conf['prevent-arp-spoofing'] and cmp_release >= 'ocata':
|
||||
@ -182,7 +215,21 @@ class OVSPluginContext(context.NeutronContext):
|
||||
if vlan_ranges:
|
||||
ovs_ctxt['vlan_ranges'] = ','.join(vlan_ranges.split())
|
||||
|
||||
ovs_ctxt['firewall_driver'] = _get_firewall_driver()
|
||||
ovs_ctxt['enable_nsg_logging'] = \
|
||||
neutron_api_settings['enable_nsg_logging']
|
||||
|
||||
ovs_ctxt['nsg_log_output_base'] = get_nsg_log_path(
|
||||
config('security-group-log-output-base')
|
||||
)
|
||||
ovs_ctxt['nsg_log_rate_limit'] = \
|
||||
config('security-group-log-rate-limit')
|
||||
ovs_ctxt['nsg_log_burst_limit'] = \
|
||||
config('security-group-log-burst-limit')
|
||||
|
||||
ovs_ctxt['firewall_driver'] = _get_firewall_driver(ovs_ctxt)
|
||||
|
||||
if ovs_ctxt['firewall_driver'] != OPENVSWITCH:
|
||||
ovs_ctxt['enable_nsg_logging'] = False
|
||||
|
||||
return ovs_ctxt
|
||||
|
||||
|
46
templates/queens/openvswitch_agent.ini
Normal file
46
templates/queens/openvswitch_agent.ini
Normal file
@ -0,0 +1,46 @@
|
||||
# queens
|
||||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
# Config managed by neutron-openvswitch charm
|
||||
###############################################################################
|
||||
[ovs]
|
||||
enable_tunneling = True
|
||||
local_ip = {{ local_ip }}
|
||||
bridge_mappings = {{ bridge_mappings }}
|
||||
{% if enable_dpdk -%}
|
||||
datapath_type = netdev
|
||||
vhostuser_socket_dir = /run/libvirt-vhost-user
|
||||
{% endif -%}
|
||||
|
||||
[agent]
|
||||
tunnel_types = {{ overlay_network_type }}
|
||||
l2_population = {{ l2_population }}
|
||||
enable_distributed_routing = {{ distributed_routing }}
|
||||
prevent_arp_spoofing = {{ prevent_arp_spoofing }}
|
||||
{% if veth_mtu -%}
|
||||
veth_mtu = {{ veth_mtu }}
|
||||
{% endif -%}
|
||||
polling_interval = {{ polling_interval }}
|
||||
{% if extension_drivers -%}
|
||||
extensions = {{ extension_drivers }}
|
||||
{% endif -%}
|
||||
|
||||
[securitygroup]
|
||||
{% if neutron_security_groups and not enable_dpdk -%}
|
||||
enable_security_group = True
|
||||
firewall_driver = {{ firewall_driver }}
|
||||
{% else -%}
|
||||
enable_security_group = False
|
||||
{% endif -%}
|
||||
|
||||
{% if enable_nsg_logging -%}
|
||||
[network_log]
|
||||
{% if nsg_log_rate_limit -%}
|
||||
rate_limit = {{ nsg_log_rate_limit }}
|
||||
{% endif -%}
|
||||
burst_limit = {{ nsg_log_burst_limit }}
|
||||
{% if nsg_log_output_base -%}
|
||||
local_output_log_base = {{ nsg_log_output_base }}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
@ -67,6 +67,7 @@ class NeutronOVSBasicDeployment(OpenStackAmuletDeployment):
|
||||
this_service = {'name': 'neutron-openvswitch'}
|
||||
other_services = [
|
||||
{'name': 'nova-compute'},
|
||||
{'name': 'nova-cloud-controller'},
|
||||
{'name': 'rabbitmq-server'},
|
||||
{'name': 'keystone'},
|
||||
{'name': 'glance'},
|
||||
@ -94,6 +95,13 @@ class NeutronOVSBasicDeployment(OpenStackAmuletDeployment):
|
||||
'glance:shared-db': 'percona-cluster:shared-db',
|
||||
'glance:amqp': 'rabbitmq-server:amqp',
|
||||
'keystone:shared-db': 'percona-cluster:shared-db',
|
||||
'nova-cloud-controller:shared-db': 'percona-cluster:shared-db',
|
||||
'nova-cloud-controller:amqp': 'rabbitmq-server:amqp',
|
||||
'nova-cloud-controller:identity-service': 'keystone:'
|
||||
'identity-service',
|
||||
'nova-cloud-controller:cloud-compute': 'nova-compute:'
|
||||
'cloud-compute',
|
||||
'nova-cloud-controller:image-service': 'glance:image-service',
|
||||
}
|
||||
super(NeutronOVSBasicDeployment, self)._add_relations(relations)
|
||||
|
||||
@ -109,9 +117,11 @@ class NeutronOVSBasicDeployment(OpenStackAmuletDeployment):
|
||||
'root-password': 'ChangeMe123',
|
||||
'sst-password': 'ChangeMe123',
|
||||
}
|
||||
nova_cc_config = {'network-manager': 'Neutron'}
|
||||
configs = {
|
||||
'neutron-openvswitch': neutron_ovs_config,
|
||||
'percona-cluster': pxc_config,
|
||||
'nova-cloud-controller': nova_cc_config,
|
||||
}
|
||||
super(NeutronOVSBasicDeployment, self)._configure_services(configs)
|
||||
|
||||
|
@ -129,7 +129,10 @@ class OVSPluginContextTest(CharmTestCase):
|
||||
'bridge-mappings': "physnet1:br-data physnet2:br-data",
|
||||
'flat-network-providers': 'physnet3 physnet4',
|
||||
'prevent-arp-spoofing': False,
|
||||
'enable-dpdk': False}
|
||||
'enable-dpdk': False,
|
||||
'security-group-log-output-base': '/var/log/nsg.log',
|
||||
'security-group-log-rate-limit': None,
|
||||
'security-group-log-burst-limit': 25}
|
||||
|
||||
def mock_config(key=None):
|
||||
if key:
|
||||
@ -183,6 +186,10 @@ class OVSPluginContextTest(CharmTestCase):
|
||||
'bridge_mappings': 'physnet1:br-data,physnet2:br-data',
|
||||
'vlan_ranges': 'physnet1:1000:1500,physnet2:2000:2500',
|
||||
'prevent_arp_spoofing': False,
|
||||
'enable_nsg_logging': False,
|
||||
'nsg_log_output_base': '/var/log/nsg.log',
|
||||
'nsg_log_rate_limit': None,
|
||||
'nsg_log_burst_limit': 25,
|
||||
}
|
||||
self.assertEqual(expect, napi_ctxt())
|
||||
|
||||
@ -259,6 +266,10 @@ class OVSPluginContextTest(CharmTestCase):
|
||||
'bridge_mappings': 'physnet1:br-data',
|
||||
'vlan_ranges': 'physnet1:1000:2000',
|
||||
'prevent_arp_spoofing': True,
|
||||
'enable_nsg_logging': False,
|
||||
'nsg_log_output_base': None,
|
||||
'nsg_log_rate_limit': None,
|
||||
'nsg_log_burst_limit': 25,
|
||||
}
|
||||
self.maxDiff = None
|
||||
self.assertEqual(expect, napi_ctxt())
|
||||
@ -755,24 +766,41 @@ class TestFirewallDriver(CharmTestCase):
|
||||
self.config.side_effect = self.test_config.get
|
||||
|
||||
def test_get_firewall_driver_xenial_unset(self):
|
||||
ctxt = {'enable_nsg_logging': False}
|
||||
self.lsb_release.return_value = _LSB_RELEASE_XENIAL
|
||||
self.assertEqual(context._get_firewall_driver(),
|
||||
self.assertEqual(context._get_firewall_driver(ctxt),
|
||||
context.IPTABLES_HYBRID)
|
||||
|
||||
def test_get_firewall_driver_xenial_openvswitch(self):
|
||||
ctxt = {'enable_nsg_logging': False}
|
||||
self.test_config.set('firewall-driver', 'openvswitch')
|
||||
self.lsb_release.return_value = _LSB_RELEASE_XENIAL
|
||||
self.assertEqual(context._get_firewall_driver(),
|
||||
self.assertEqual(context._get_firewall_driver(ctxt),
|
||||
context.OPENVSWITCH)
|
||||
|
||||
def test_get_firewall_driver_xenial_invalid(self):
|
||||
ctxt = {'enable_nsg_logging': False}
|
||||
self.test_config.set('firewall-driver', 'foobar')
|
||||
self.lsb_release.return_value = _LSB_RELEASE_XENIAL
|
||||
self.assertEqual(context._get_firewall_driver(),
|
||||
self.assertEqual(context._get_firewall_driver(ctxt),
|
||||
context.IPTABLES_HYBRID)
|
||||
|
||||
def test_get_firewall_driver_trusty_openvswitch(self):
|
||||
ctxt = {'enable_nsg_logging': False}
|
||||
self.test_config.set('firewall-driver', 'openvswitch')
|
||||
self.lsb_release.return_value = _LSB_RELEASE_TRUSTY
|
||||
self.assertEqual(context._get_firewall_driver(),
|
||||
self.assertEqual(context._get_firewall_driver(ctxt),
|
||||
context.IPTABLES_HYBRID)
|
||||
|
||||
def test_get_firewall_driver_nsg_logging(self):
|
||||
ctxt = {'enable_nsg_logging': True}
|
||||
self.lsb_release.return_value = _LSB_RELEASE_XENIAL
|
||||
self.test_config.set('firewall-driver', 'openvswitch')
|
||||
self.assertEqual(context._get_firewall_driver(ctxt),
|
||||
context.OPENVSWITCH)
|
||||
|
||||
def test_get_firewall_driver_nsg_logging_iptables_hybrid(self):
|
||||
ctxt = {'enable_nsg_logging': True}
|
||||
self.lsb_release.return_value = _LSB_RELEASE_XENIAL
|
||||
self.assertEqual(context._get_firewall_driver(ctxt),
|
||||
context.IPTABLES_HYBRID)
|
||||
|
Loading…
Reference in New Issue
Block a user