summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-06-27 14:58:29 +0200
committerGitHub <noreply@github.com>2020-06-27 14:58:29 +0200
commit4aca048919b2237ce065bf22a775d782e780ff5a (patch)
tree8e9de4aeceba264e3d17f2a385a0e442cbab89de /src/conf_mode
parent1d97d52120eaa33a3c2edb39e966002dab7f9576 (diff)
parentadfb4c81a41b9eec4b33a27a8d8db7184dbda6da (diff)
downloadvyos-1x-4aca048919b2237ce065bf22a775d782e780ff5a.tar.gz
vyos-1x-4aca048919b2237ce065bf22a775d782e780ff5a.zip
Merge pull request #480 from c-po/t2653
ifconfig: T2653: move macsec interface to get_config_dict()
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/interfaces-dummy.py12
-rwxr-xr-xsrc/conf_mode/interfaces-loopback.py10
-rwxr-xr-xsrc/conf_mode/interfaces-macsec.py209
3 files changed, 73 insertions, 158 deletions
diff --git a/src/conf_mode/interfaces-dummy.py b/src/conf_mode/interfaces-dummy.py
index 676211428..a8093ffa5 100755
--- a/src/conf_mode/interfaces-dummy.py
+++ b/src/conf_mode/interfaces-dummy.py
@@ -41,6 +41,10 @@ def get_config():
base = ['interfaces', 'dummy', ifname]
dummy = conf.get_config_dict(base, key_mangling=('-', '_'))
+ # Check if interface has been removed
+ if dummy == {}:
+ dummy.update({'deleted' : ''})
+
# store interface instance name in dictionary
dummy.update({'ifname': ifname})
@@ -50,14 +54,10 @@ def get_config():
tmp = {'is_bridge_member' : bridge}
dummy.update(tmp)
- # Check if interface has been removed
- tmp = {'deleted' : not conf.exists(base)}
- dummy.update(tmp)
-
return dummy
def verify(dummy):
- if dummy['deleted']:
+ if 'deleted' in dummy.keys():
verify_bridge_delete(dummy)
return None
@@ -73,7 +73,7 @@ def apply(dummy):
d = DummyIf(dummy['ifname'])
# Remove dummy interface
- if dummy['deleted']:
+ if 'deleted' in dummy.keys():
d.remove()
else:
d.update(dummy)
diff --git a/src/conf_mode/interfaces-loopback.py b/src/conf_mode/interfaces-loopback.py
index 32e683c07..7c3d8663d 100755
--- a/src/conf_mode/interfaces-loopback.py
+++ b/src/conf_mode/interfaces-loopback.py
@@ -36,13 +36,13 @@ def get_config():
base = ['interfaces', 'loopback', ifname]
loopback = conf.get_config_dict(base, key_mangling=('-', '_'))
+ # Check if interface has been removed
+ if loopback == {}:
+ loopback.update({'deleted' : ''})
+
# store interface instance name in dictionary
loopback.update({'ifname': ifname})
- # Check if interface has been removed
- tmp = {'deleted' : not conf.exists(base)}
- loopback.update(tmp)
-
return loopback
def verify(loopback):
@@ -53,7 +53,7 @@ def generate(loopback):
def apply(loopback):
l = LoopbackIf(loopback['ifname'])
- if loopback['deleted']:
+ if 'deleted' in loopback.keys():
l.remove()
else:
l.update(loopback)
diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py
index a8966148f..ca5c32eeb 100755
--- a/src/conf_mode/interfaces-macsec.py
+++ b/src/conf_mode/interfaces-macsec.py
@@ -18,177 +18,111 @@ import os
from copy import deepcopy
from sys import exit
-from netifaces import interfaces
from vyos.config import Config
-from vyos.configdict import list_diff
+from vyos.configdict import dict_merge
from vyos.ifconfig import MACsecIf
from vyos.template import render
from vyos.util import call
from vyos.validate import is_member
+from vyos.configverify import verify_bridge_vrf
+from vyos.configverify import verify_bridge_address
+from vyos.configverify import verify_bridge_delete
+from vyos.configverify import verify_source_interface
+from vyos.xml import defaults
from vyos import ConfigError
-
from vyos import airbag
airbag.enable()
-default_config_data = {
- 'address': [],
- 'address_remove': [],
- 'deleted': False,
- 'description': '',
- 'disable': False,
- 'security_cipher': '',
- 'security_encrypt': False,
- 'security_mka_cak': '',
- 'security_mka_ckn': '',
- 'security_mka_priority': '255',
- 'security_replay_window': '',
- 'intf': '',
- 'source_interface': '',
- 'is_bridge_member': False,
- 'vrf': ''
-}
+# XXX: workaround for https://phabricator.vyos.net/T2656
+default = {'security' : {'mka' : {'priority' : '255'}}}
# XXX: wpa_supplicant works on the source interface
wpa_suppl_conf = '/run/wpa_supplicant/{source_interface}.conf'
-
def get_config():
- macsec = deepcopy(default_config_data)
+ """ Retrive CLI config as dictionary. Dictionary can never be empty,
+ as at least the interface name will be added or a deleted flag """
conf = Config()
# determine tagNode instance
if 'VYOS_TAGNODE_VALUE' not in os.environ:
raise ConfigError('Interface (VYOS_TAGNODE_VALUE) not specified')
- macsec['intf'] = os.environ['VYOS_TAGNODE_VALUE']
- base_path = ['interfaces', 'macsec', macsec['intf']]
+ # retrieve interface default values
+ base = ['interfaces', 'macsec']
+ #default_values = defaults(base)
- # check if we are a member of any bridge
- macsec['is_bridge_member'] = is_member(conf, macsec['intf'], 'bridge')
+ ifname = os.environ['VYOS_TAGNODE_VALUE']
+ base = base + [ifname]
+ macsec = conf.get_config_dict(base, key_mangling=('-', '_'))
# Check if interface has been removed
- if not conf.exists(base_path):
- macsec['deleted'] = True
- # When stopping wpa_supplicant we need to stop it via the physical
- # interface - thus we need to retrieve ir from the effective config
- if conf.exists_effective(base_path + ['source-interface']):
- macsec['source_interface'] = conf.return_effective_value(
- base_path + ['source-interface'])
-
- return macsec
-
- # set new configuration level
- conf.set_level(base_path)
-
- # retrieve configured interface addresses
- if conf.exists(['address']):
- macsec['address'] = conf.return_values(['address'])
-
- # retrieve interface description
- if conf.exists(['description']):
- macsec['description'] = conf.return_value(['description'])
-
- # Disable this interface
- if conf.exists(['disable']):
- macsec['disable'] = True
-
- # retrieve interface cipher
- if conf.exists(['security', 'cipher']):
- macsec['security_cipher'] = conf.return_value(['security', 'cipher'])
-
- # Enable optional MACsec encryption
- if conf.exists(['security', 'encrypt']):
- macsec['security_encrypt'] = True
-
- # Secure Connectivity Association Key
- if conf.exists(['security', 'mka', 'cak']):
- macsec['security_mka_cak'] = conf.return_value(
- ['security', 'mka', 'cak'])
-
- # Secure Connectivity Association Name
- if conf.exists(['security', 'mka', 'ckn']):
- macsec['security_mka_ckn'] = conf.return_value(
- ['security', 'mka', 'ckn'])
-
- # MACsec Key Agreement protocol (MKA) actor priority
- if conf.exists(['security', 'mka', 'priority']):
- macsec['security_mka_priority'] = conf.return_value(
- ['security', 'mka', 'priority'])
-
- # IEEE 802.1X/MACsec replay protection
- if conf.exists(['security', 'replay-window']):
- macsec['security_replay_window'] = conf.return_value(
- ['security', 'replay-window'])
-
- # Physical interface
- if conf.exists(['source-interface']):
- macsec['source_interface'] = conf.return_value(['source-interface'])
-
- # Determine interface addresses (currently effective) - to determine which
- # address is no longer valid and needs to be removed from the interface
- eff_addr = conf.return_effective_values(['address'])
- act_addr = conf.return_values(['address'])
- macsec['address_remove'] = list_diff(eff_addr, act_addr)
-
- # retrieve VRF instance
- if conf.exists(['vrf']):
- macsec['vrf'] = conf.return_value(['vrf'])
+ if macsec == {}:
+ tmp = {
+ 'deleted' : '',
+ 'source_interface' : conf.return_effective_value(
+ base + ['source-interface'])
+ }
+ macsec.update(tmp)
+
+ # We have gathered the dict representation of the CLI, but there are
+ # default options which we need to update into the dictionary
+ # retrived.
+ macsec = dict_merge(default, macsec)
+
+ # Add interface instance name into dictionary
+ macsec.update({'ifname': ifname})
+
+ # Check if we are a member of any bridge
+ bridge = is_member(conf, ifname, 'bridge')
+ if bridge:
+ tmp = {'is_bridge_member' : bridge}
+ macsec.update(tmp)
return macsec
def verify(macsec):
- if macsec['deleted']:
- if macsec['is_bridge_member']:
- raise ConfigError(
- 'Interface "{intf}" cannot be deleted as it is a '
- 'member of bridge "{is_bridge_member}"!'.format(**macsec))
-
+ if 'deleted' in macsec.keys():
+ verify_bridge_delete(macsec)
return None
- if not macsec['source_interface']:
- raise ConfigError('Physical source interface must be set for '
- 'MACsec "{intf}"'.format(**macsec))
+ verify_source_interface(macsec)
+ verify_bridge_vrf(macsec)
+ verify_bridge_address(macsec)
- if not macsec['security_cipher']:
+ if not (('security' in macsec.keys()) and
+ ('cipher' in macsec['security'].keys())):
raise ConfigError(
- 'Cipher suite must be set for MACsec "{intf}"'.format(**macsec))
+ 'Cipher suite must be set for MACsec "{ifname}"'.format(**macsec))
- if macsec['security_encrypt']:
- if not (macsec['security_mka_cak'] and macsec['security_mka_ckn']):
- raise ConfigError(
- 'MACsec security keys mandartory when encryption is enabled')
+ if (('security' in macsec.keys()) and
+ ('encrypt' in macsec['security'].keys())):
+ tmp = macsec.get('security')
- if macsec['vrf']:
- if macsec['vrf'] not in interfaces():
- raise ConfigError('VRF "{vrf}" does not exist'.format(**macsec))
-
- if macsec['is_bridge_member']:
- raise ConfigError('Interface "{intf}" cannot be member of VRF '
- '"{vrf}" and bridge "{is_bridge_member}" at '
- 'the same time!'.format(**macsec))
-
- if macsec['is_bridge_member'] and macsec['address']:
- raise ConfigError(
- 'Cannot assign address to interface "{intf}" as it is'
- 'a member of bridge "{is_bridge_member}"!'.format(**macsec))
+ if not (('mka' in tmp.keys()) and
+ ('cak' in tmp['mka'].keys()) and
+ ('ckn' in tmp['mka'].keys())):
+ raise ConfigError('Missing mandatory MACsec security '
+ 'keys as encryption is enabled!')
return None
def generate(macsec):
render(wpa_suppl_conf.format(**macsec),
- 'macsec/wpa_supplicant.conf.tmpl', macsec, permission=0o640)
+ 'macsec/wpa_supplicant.conf.tmpl', macsec)
return None
def apply(macsec):
# Remove macsec interface
- if macsec['deleted']:
+ if 'deleted' in macsec.keys():
call('systemctl stop wpa_supplicant-macsec@{source_interface}'
.format(**macsec))
- MACsecIf(macsec['intf']).remove()
+
+ MACsecIf(macsec['ifname']).remove()
# delete configuration on interface removal
if os.path.isfile(wpa_suppl_conf.format(**macsec)):
@@ -198,35 +132,16 @@ def apply(macsec):
# MACsec interfaces require a configuration when they are added using
# iproute2. This static method will provide the configuration
# dictionary used by this class.
- conf = deepcopy(MACsecIf.get_config())
- # Assign MACsec instance configuration parameters to config dict
+ # XXX: subject of removal after completing T2653
+ conf = deepcopy(MACsecIf.get_config())
conf['source_interface'] = macsec['source_interface']
- conf['security_cipher'] = macsec['security_cipher']
+ conf['security_cipher'] = macsec['security']['cipher']
# It is safe to "re-create" the interface always, there is a sanity
# check that the interface will only be create if its non existent
- i = MACsecIf(macsec['intf'], **conf)
-
- # update interface description used e.g. within SNMP
- i.set_alias(macsec['description'])
-
- # Configure interface address(es)
- # - not longer required addresses get removed first
- # - newly addresses will be added second
- for addr in macsec['address_remove']:
- i.del_addr(addr)
- for addr in macsec['address']:
- i.add_addr(addr)
-
- # assign/remove VRF (ONLY when not a member of a bridge,
- # otherwise 'nomaster' removes it from it)
- if not macsec['is_bridge_member']:
- i.set_vrf(macsec['vrf'])
-
- # Interface is administratively down by default, enable if desired
- if not macsec['disable']:
- i.set_admin_state('up')
+ i = MACsecIf(macsec['ifname'], **conf)
+ i.update(macsec)
call('systemctl restart wpa_supplicant-macsec@{source_interface}'
.format(**macsec))