From d457ef195293b8f4971ecded227134f0bec0fc0a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 20 May 2020 21:02:59 +0200 Subject: macvlan: T2023: prepare common source interface include file --- .../include/source-interface-ethernet.xml.i | 12 ++++++++++++ interface-definitions/interfaces-pseudo-ethernet.xml.in | 13 +------------ 2 files changed, 13 insertions(+), 12 deletions(-) create mode 100644 interface-definitions/include/source-interface-ethernet.xml.i (limited to 'interface-definitions') diff --git a/interface-definitions/include/source-interface-ethernet.xml.i b/interface-definitions/include/source-interface-ethernet.xml.i new file mode 100644 index 000000000..ad90bc4ac --- /dev/null +++ b/interface-definitions/include/source-interface-ethernet.xml.i @@ -0,0 +1,12 @@ + + + Physical interface the traffic will go through + + interface + Physical interface used for traffic forwarding + + + + + + diff --git a/interface-definitions/interfaces-pseudo-ethernet.xml.in b/interface-definitions/interfaces-pseudo-ethernet.xml.in index 61fd6c9fd..d5f9ca661 100644 --- a/interface-definitions/interfaces-pseudo-ethernet.xml.in +++ b/interface-definitions/interfaces-pseudo-ethernet.xml.in @@ -41,18 +41,7 @@ #include - - - Physical Interface used for this device - - interface - Physical interface used for this pseudo device - - - - - - + #include #include -- cgit v1.2.3 From fe9d399a4e78a1637cb3a693e0470eaec1dd5de5 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Wed, 20 May 2020 21:09:59 +0200 Subject: macsec: T2023: add initial XML and Python interfaces --- interface-definitions/interfaces-macsec.xml.in | 47 +++++++ src/conf_mode/interfaces-macsec.py | 178 +++++++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 interface-definitions/interfaces-macsec.xml.in create mode 100755 src/conf_mode/interfaces-macsec.py (limited to 'interface-definitions') diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in new file mode 100644 index 000000000..79837dfb5 --- /dev/null +++ b/interface-definitions/interfaces-macsec.xml.in @@ -0,0 +1,47 @@ + + + + + + + MACsec Interface (802.1ae) + 319 + + ^macsec[0-9]+$ + + MACsec interface must be named macsecN + + macsecN + MACsec interface name + + + + #include + + + Cipher suite used (default: gcm-aes-128) + + gcm-aes-128 gcm-aes-256 + + + gcm-aes-128 + Galois/Counter Mode of AES cipher with 128-bit key (default) + + + gcm-aes-256 + Galois/Counter Mode of AES cipher with 256-bit key + + + (gcm-aes-128|gcm-aes-256) + + + + #include + #include + #include + #include + + + + + diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py new file mode 100755 index 000000000..db605295e --- /dev/null +++ b/src/conf_mode/interfaces-macsec.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os + +from copy import deepcopy +from sys import exit +from netifaces import interfaces + +from vyos.ifconfig import MACsecIf +from vyos.configdict import list_diff +from vyos.config import Config +from vyos.validate import is_member +from vyos import ConfigError + +default_config_data = { + 'address': [], + 'address_remove': [], + 'cipher': 'gcm-aes-128', + 'deleted': False, + 'description': '', + 'disable': False, + 'intf': '', + 'source_interface': '', + 'is_bridge_member': False, + 'vrf': '' +} + +def get_config(): + macsec = deepcopy(default_config_data) + 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'] + + # check if we are a member of any bridge + macsec['is_bridge_member'] = is_member(conf, macsec['intf'], 'bridge') + + # Check if interface has been removed + if not conf.exists('interfaces macsec ' + macsec['intf']): + macsec['deleted'] = True + return macsec + + # set new configuration level + conf.set_level('interfaces macsec ' + macsec['intf']) + + # retrieve configured interface addresses + if conf.exists('address'): + macsec['address'] = conf.return_values('address') + + # retrieve interface cipher + if conf.exists('cipher'): + macsec['cipher'] = conf.return_value('cipher') + + # retrieve interface description + if conf.exists('description'): + macsec['description'] = conf.return_value('description') + + # Disable this interface + if conf.exists('disable'): + macsec['disable'] = True + + # 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') + + return macsec + +def verify(macsec): + if macsec['deleted']: + if macsec['is_bridge_member']: + raise ConfigError(( + f'Interface "{macsec["intf"]}" cannot be deleted as it is a ' + f'member of bridge "{macsec["is_bridge_member"]}"!')) + + return None + + if not macsec['source_interface']: + raise ConfigError(( + f'Physical source interface must be set for MACsec "{macsec["intf"]}"')) + + if macsec['vrf']: + if macsec['vrf'] not in interfaces(): + raise ConfigError(f'VRF "{macsec["vrf"]}" does not exist') + + if macsec['is_bridge_member']: + raise ConfigError(( + f'Interface "{macsec["intf"]}" cannot be member of VRF ' + f'"{macsec["vrf"]}" and bridge "{macsec["is_bridge_member"]}" ' + f'at the same time!')) + + if macsec['is_bridge_member'] and macsec['address']: + raise ConfigError(( + f'Cannot assign address to interface "{macsec["intf"]}" ' + f'as it is a member of bridge "{macsec["is_bridge_member"]}"!')) + + return None + +def generate(macsec): + return None + +def apply(macsec): + # Remove macsec interface + if macsec['deleted']: + MACsecIf(macsec['intf']).remove() + else: + # 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 + conf['source_interface'] = macsec['source_interface'] + conf['cipher'] = macsec['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']) + + # disable interface on demand + if macsec['disable']: + i.set_admin_state('down') + else: + i.set_admin_state('up') + + return None + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + exit(1) -- cgit v1.2.3 From 04d03f5bdd262bbf95f09e6ba3f211ab1d459573 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 21 May 2020 10:43:44 +0200 Subject: macsec: T2023: add optional encryption command By default MACsec only authenticates traffic but has support for optional encryption. Encryption can now be enabled using: set interfaces macsec encrypt --- interface-definitions/interfaces-macsec.xml.in | 6 ++++++ python/vyos/ifconfig/macsec.py | 7 ++++++- src/conf_mode/interfaces-macsec.py | 14 ++++++++++---- 3 files changed, 22 insertions(+), 5 deletions(-) (limited to 'interface-definitions') diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index 79837dfb5..13448e758 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -36,6 +36,12 @@ + + + Enable optional MACsec encryption + + + #include #include #include diff --git a/python/vyos/ifconfig/macsec.py b/python/vyos/ifconfig/macsec.py index cea3f8d13..1829df4ab 100644 --- a/python/vyos/ifconfig/macsec.py +++ b/python/vyos/ifconfig/macsec.py @@ -50,12 +50,17 @@ class MACsecIf(Interface): """ # create tunnel interface cmd = 'ip link add link {source_interface} {ifname} type {type}' - cmd += ' cipher {cipher} encrypt on' + cmd += ' cipher {cipher}' self._cmd(cmd.format(**self.config)) # interface is always A/D down. It needs to be enabled explicitly self.set_admin_state('down') + def set_encryption(self, on_off): + ifname = self.config['ifname'] + cmd = f'ip link set {ifname} type macsec encrypt {on_off}' + return self._cmd(cmd) + @staticmethod def get_config(): """ diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index db605295e..fcf23ed0f 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -33,6 +33,7 @@ default_config_data = { 'deleted': False, 'description': '', 'disable': False, + 'encrypt': 'off', 'intf': '', 'source_interface': '', 'is_bridge_member': False, @@ -76,6 +77,10 @@ def get_config(): if conf.exists('disable'): macsec['disable'] = True + # Enable optional MACsec encryption + if conf.exists('encrypt'): + macsec['encrypt'] = 'on' + # Physical interface if conf.exists(['source-interface']): macsec['source_interface'] = conf.return_value(['source-interface']) @@ -143,6 +148,9 @@ def apply(macsec): # that the interface will only be create if its non existent i = MACsecIf(macsec['intf'], **conf) + # Configure optional encryption + i.set_encryption(macsec['encrypt']) + # update interface description used e.g. within SNMP i.set_alias(macsec['description']) @@ -159,10 +167,8 @@ def apply(macsec): if not macsec['is_bridge_member']: i.set_vrf(macsec['vrf']) - # disable interface on demand - if macsec['disable']: - i.set_admin_state('down') - else: + # Interface is administratively down by default, enable if desired + if not macsec['disable']: i.set_admin_state('up') return None -- cgit v1.2.3 From f48f19063561639d65b76f241f17f0704ba69644 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 21 May 2020 11:13:56 +0200 Subject: macsec: T2023: remove gcm-aes-256 cipher type Cipher type gcm-aes-256 is supported by Linux 4.19 but it is not available in iproute2 4.19. We could backport it of course but the plan is to Upgrade to a more recent 5.x series kernel anyway once all out-of-tree module issues are resolved, mainly Intel QAT. gcm-aes-256 support was added to iproute2 package with commit b16f5253233 ("Add support for configuring MACsec gcm-aes-256 cipher type.") which made it into the 5.2 release of iproute2. --- interface-definitions/interfaces-macsec.xml.in | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'interface-definitions') diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index 13448e758..f16760112 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -19,20 +19,16 @@ #include - Cipher suite used (default: gcm-aes-128) + Cipher suite used - gcm-aes-128 gcm-aes-256 + gcm-aes-128 gcm-aes-128 Galois/Counter Mode of AES cipher with 128-bit key (default) - - gcm-aes-256 - Galois/Counter Mode of AES cipher with 256-bit key - - (gcm-aes-128|gcm-aes-256) + (gcm-aes-128) -- cgit v1.2.3 From 63a3110298e5f3f6d24d5ed57eff0a8abf27f6ac Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 21 May 2020 12:48:09 +0200 Subject: macsec: T2023: cli: move "cipher" and "encryption" under new "secutiry" node This is best suited as a key is required, too. --- interface-definitions/interfaces-macsec.xml.in | 45 +++++++++++++++----------- src/conf_mode/interfaces-macsec.py | 15 +++++---- 2 files changed, 34 insertions(+), 26 deletions(-) (limited to 'interface-definitions') diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index f16760112..53a347f11 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -17,27 +17,34 @@ #include - + - Cipher suite used - - gcm-aes-128 - - - gcm-aes-128 - Galois/Counter Mode of AES cipher with 128-bit key (default) - - - (gcm-aes-128) - + Security/Encryption Settings - - - - Enable optional MACsec encryption - - - + + + + Cipher suite used + + gcm-aes-128 + + + gcm-aes-128 + Galois/Counter Mode of AES cipher with 128-bit key (default) + + + (gcm-aes-128) + + + + + + Enable optional MACsec encryption + + + + + #include #include #include diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index 867df3eb6..fefc50d99 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -20,9 +20,10 @@ from copy import deepcopy from sys import exit from netifaces import interfaces -from vyos.ifconfig import MACsecIf -from vyos.configdict import list_diff from vyos.config import Config +from vyos.configdict import list_diff +from vyos.ifconfig import MACsecIf +from vyos.template import render from vyos.validate import is_member from vyos import ConfigError @@ -66,10 +67,6 @@ def get_config(): if conf.exists(['address']): macsec['address'] = conf.return_values(['address']) - # retrieve interface cipher - if conf.exists(['cipher']): - macsec['cipher'] = conf.return_value(['cipher']) - # retrieve interface description if conf.exists(['description']): macsec['description'] = conf.return_value(['description']) @@ -78,8 +75,12 @@ def get_config(): if conf.exists(['disable']): macsec['disable'] = True + # retrieve interface cipher + if conf.exists(['security', 'cipher']): + macsec['cipher'] = conf.return_value(['security', 'cipher']) + # Enable optional MACsec encryption - if conf.exists(['encrypt']): + if conf.exists(['security', 'encrypt']): macsec['encrypt'] = 'on' # Physical interface -- cgit v1.2.3 From 3872f5995644a8a52358285d682a7103b54dde04 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 21 May 2020 13:55:32 +0200 Subject: macsec: T2023: use wpa_supplicant for key management --- data/templates/macsec/wpa_supplicant.conf.tmpl | 53 ++++++++++++++++++++++++++ interface-definitions/interfaces-macsec.xml.in | 23 +++++++++++ python/vyos/ifconfig/macsec.py | 13 ++----- src/conf_mode/interfaces-macsec.py | 36 ++++++++++++----- src/systemd/wpa_supplicant-macsec@.service | 16 ++++++++ 5 files changed, 122 insertions(+), 19 deletions(-) create mode 100644 data/templates/macsec/wpa_supplicant.conf.tmpl create mode 100644 src/systemd/wpa_supplicant-macsec@.service (limited to 'interface-definitions') diff --git a/data/templates/macsec/wpa_supplicant.conf.tmpl b/data/templates/macsec/wpa_supplicant.conf.tmpl new file mode 100644 index 000000000..b73d4b863 --- /dev/null +++ b/data/templates/macsec/wpa_supplicant.conf.tmpl @@ -0,0 +1,53 @@ +# autogenerated by interfaces-macsec.py + +# see full documentation: +# https://w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf + +# For UNIX domain sockets (default on Linux and BSD): This is a directory that +# will be created for UNIX domain sockets for listening to requests from +# external programs (CLI/GUI, etc.) for status information and configuration. +# The socket file will be named based on the interface name, so multiple +# wpa_supplicant processes can be run at the same time if more than one +# interface is used. +# /var/run/wpa_supplicant is the recommended directory for sockets and by +# default, wpa_cli will use it when trying to connect with wpa_supplicant. +ctrl_interface=/run/wpa_supplicant + +# Note: When using MACsec, eapol_version shall be set to 3, which is +# defined in IEEE Std 802.1X-2010. +eapol_version=3 + +# No need to scan for access points in MACsec mode +ap_scan=0 + +# EAP fast re-authentication +fast_reauth=1 + +network={ + key_mgmt=NONE + + # Note: When using wired authentication (including MACsec drivers), + # eapol_flags must be set to 0 for the authentication to be completed + # successfully. + eapol_flags=0 + + # macsec_policy: IEEE 802.1X/MACsec options + # This determines how sessions are secured with MACsec (only for MACsec + # drivers). + # 0: MACsec not in use (default) + # 1: MACsec enabled - Should secure, accept key server's advice to + # determine whether to use a secure session or not. + macsec_policy=1 + + # macsec_integ_only: IEEE 802.1X/MACsec transmit mode + # This setting applies only when MACsec is in use, i.e., + # - macsec_policy is enabled + # - the key server has decided to enable MACsec + # 0: Encrypt traffic (default) + # 1: Integrity only + macsec_integ_only={{ '0' if security_encrypt else '1' }} + + mka_cak={{ security_key_cak }} + mka_ckn={{ security_key_ckn }} +} + diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index 53a347f11..f76fef298 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -43,6 +43,29 @@ + + + Encryption keys + + + + + Secure Connectivity Association Key + + ^[A-Fa-f0-9]{32}$ + + + + + + Secure Connectivity Association Key Name + + ^[A-Fa-f0-9]{64}$ + + + + + #include diff --git a/python/vyos/ifconfig/macsec.py b/python/vyos/ifconfig/macsec.py index 1829df4ab..ea8c9807e 100644 --- a/python/vyos/ifconfig/macsec.py +++ b/python/vyos/ifconfig/macsec.py @@ -30,7 +30,7 @@ class MACsecIf(Interface): default = { 'type': 'macsec', - 'cipher': '', + 'security_cipher': '', 'source_interface': '' } definition = { @@ -41,7 +41,7 @@ class MACsecIf(Interface): }, } options = Interface.options + \ - ['cipher', 'source_interface'] + ['security_cipher', 'source_interface'] def _create(self): """ @@ -50,17 +50,12 @@ class MACsecIf(Interface): """ # create tunnel interface cmd = 'ip link add link {source_interface} {ifname} type {type}' - cmd += ' cipher {cipher}' + cmd += ' cipher {security_cipher}' self._cmd(cmd.format(**self.config)) # interface is always A/D down. It needs to be enabled explicitly self.set_admin_state('down') - def set_encryption(self, on_off): - ifname = self.config['ifname'] - cmd = f'ip link set {ifname} type macsec encrypt {on_off}' - return self._cmd(cmd) - @staticmethod def get_config(): """ @@ -72,7 +67,7 @@ class MACsecIf(Interface): >> dict = MACsecIf().get_config() """ config = { - 'cipher': '', + 'security_cipher': '', 'source_interface': '', } return config diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index fefc50d99..e59df6f90 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -22,19 +22,22 @@ from netifaces import interfaces from vyos.config import Config from vyos.configdict import list_diff -from vyos.ifconfig import MACsecIf +from vyos.ifconfig import MACsecIf, Interface from vyos.template import render +from vyos.util import call from vyos.validate import is_member from vyos import ConfigError default_config_data = { 'address': [], 'address_remove': [], - 'cipher': '', 'deleted': False, 'description': '', 'disable': False, - 'encrypt': 'off', + 'security_cipher': '', + 'security_encrypt': False, + 'security_key_cak': '', + 'security_key_ckn': '', 'intf': '', 'source_interface': '', 'is_bridge_member': False, @@ -77,11 +80,19 @@ def get_config(): # retrieve interface cipher if conf.exists(['security', 'cipher']): - macsec['cipher'] = conf.return_value(['security', 'cipher']) + macsec['security_cipher'] = conf.return_value(['security', 'cipher']) # Enable optional MACsec encryption if conf.exists(['security', 'encrypt']): - macsec['encrypt'] = 'on' + macsec['security_encrypt'] = True + + # Secure Connectivity Association Key + if conf.exists(['security', 'key', 'cak']): + macsec['security_key_cak'] = conf.return_value(['security', 'key', 'cak']) + + # Secure Connectivity Association Name + if conf.exists(['security', 'key', 'ckn']): + macsec['security_key_ckn'] = conf.return_value(['security', 'key', 'ckn']) # Physical interface if conf.exists(['source-interface']): @@ -112,7 +123,7 @@ def verify(macsec): raise ConfigError(( f'Physical source interface must be set for MACsec "{macsec["intf"]}"')) - if not macsec['cipher']: + if not macsec['security_cipher']: raise ConfigError(( f'Cipher suite is mandatory for MACsec "{macsec["intf"]}"')) @@ -134,12 +145,18 @@ def verify(macsec): return None def generate(macsec): + # XXX: wpa_supplicant works on the source interface not the resulting + # MACsec interface + conf = f'/run/wpa_supplicant/wpa_supplicant-{macsec["source_interface"]}.conf' + render(conf, 'macsec/wpa_supplicant.conf.tmpl', macsec, permission=0o640) return None def apply(macsec): # Remove macsec interface if macsec['deleted']: + call(f'systemctl stop wpa_supplicant-@{macsec["intf"]}.service') MACsecIf(macsec['intf']).remove() + else: # MACsec interfaces require a configuration when they are added using # iproute2. This static method will provide the configuration @@ -148,15 +165,12 @@ def apply(macsec): # Assign MACsec instance configuration parameters to config dict conf['source_interface'] = macsec['source_interface'] - conf['cipher'] = macsec['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) - # Configure optional encryption - i.set_encryption(macsec['encrypt']) - # update interface description used e.g. within SNMP i.set_alias(macsec['description']) @@ -177,6 +191,8 @@ def apply(macsec): if not macsec['disable']: i.set_admin_state('up') + call(f'systemctl restart wpa_supplicant-macsec@{macsec["source_interface"]}.service') + return None if __name__ == '__main__': diff --git a/src/systemd/wpa_supplicant-macsec@.service b/src/systemd/wpa_supplicant-macsec@.service new file mode 100644 index 000000000..7ad12e54e --- /dev/null +++ b/src/systemd/wpa_supplicant-macsec@.service @@ -0,0 +1,16 @@ +[Unit] +Description=WPA supplicant daemon (macsec-specific version) +Requires=sys-subsystem-net-devices-%i.device +ConditionPathExists=/run/wpa_supplicant/wpa_supplicant-%I.conf +After=vyos-router.service +RequiresMountsFor=/run + +# NetworkManager users will probably want the dbus version instead. + +[Service] +Type=simple +WorkingDirectory=/run/wpa_supplicant +ExecStart=/sbin/wpa_supplicant -c /run/wpa_supplicant/wpa_supplicant-%I.conf -Dmacsec_linux -i%I + +[Install] +WantedBy=multi-user.target -- cgit v1.2.3 From 68d54d8d79f257497c884b392a7e316e9a8e7d21 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 21 May 2020 15:04:24 +0200 Subject: macsec: T2023: rename "security key" node to "security mka" MACsec always talks about MKA (MACsec Key Agreement protocol) thus the node should reflect that. --- data/templates/macsec/wpa_supplicant.conf.tmpl | 12 ++++++++++-- interface-definitions/interfaces-macsec.xml.in | 4 ++-- op-mode-definitions/generate-macsec-key.xml | 8 ++++---- src/conf_mode/interfaces-macsec.py | 13 +++++++------ 4 files changed, 23 insertions(+), 14 deletions(-) (limited to 'interface-definitions') diff --git a/data/templates/macsec/wpa_supplicant.conf.tmpl b/data/templates/macsec/wpa_supplicant.conf.tmpl index b73d4b863..df7b6f153 100644 --- a/data/templates/macsec/wpa_supplicant.conf.tmpl +++ b/data/templates/macsec/wpa_supplicant.conf.tmpl @@ -47,7 +47,15 @@ network={ # 1: Integrity only macsec_integ_only={{ '0' if security_encrypt else '1' }} - mka_cak={{ security_key_cak }} - mka_ckn={{ security_key_ckn }} + # mka_cak, mka_ckn, and mka_priority: IEEE 802.1X/MACsec pre-shared key mode + # This allows to configure MACsec with a pre-shared key using a (CAK,CKN) pair. + # In this mode, instances of wpa_supplicant can act as MACsec peers. The peer + # with lower priority will become the key server and start distributing SAKs. + # mka_cak (CAK = Secure Connectivity Association Key) takes a 16-byte (128-bit) + # hex-string (32 hex-digits) or a 32-byte (256-bit) hex-string (64 hex-digits) + # mka_ckn (CKN = CAK Name) takes a 1..32-bytes (8..256 bit) hex-string + # (2..64 hex-digits) + mka_cak={{ security_mka_cak }} + mka_ckn={{ security_mka_ckn }} } diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index f76fef298..02e6e7b3f 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -43,9 +43,9 @@ - + - Encryption keys + MACsec Key Agreement protocol (MKA) diff --git a/op-mode-definitions/generate-macsec-key.xml b/op-mode-definitions/generate-macsec-key.xml index 003669827..40d2b9061 100644 --- a/op-mode-definitions/generate-macsec-key.xml +++ b/op-mode-definitions/generate-macsec-key.xml @@ -2,18 +2,18 @@ - + - Generate MACsec secure channel key + Generate MACsec Key - + Generate MACsec connectivity association key (CAK) /usr/bin/hexdump -n 16 -e '4/4 "%08x" 1 "\n"' /dev/random - + Generate MACsec connectivity association name (CKN) diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index e59df6f90..79c57d978 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -36,8 +36,9 @@ default_config_data = { 'disable': False, 'security_cipher': '', 'security_encrypt': False, - 'security_key_cak': '', - 'security_key_ckn': '', + 'security_mka_cak': '', + 'security_mka_ckn': '', + 'security_mka_priority': '255', 'intf': '', 'source_interface': '', 'is_bridge_member': False, @@ -87,12 +88,12 @@ def get_config(): macsec['security_encrypt'] = True # Secure Connectivity Association Key - if conf.exists(['security', 'key', 'cak']): - macsec['security_key_cak'] = conf.return_value(['security', 'key', 'cak']) + if conf.exists(['security', 'mka', 'cak']): + macsec['security_mka_cak'] = conf.return_value(['security', 'mka', 'cak']) # Secure Connectivity Association Name - if conf.exists(['security', 'key', 'ckn']): - macsec['security_key_ckn'] = conf.return_value(['security', 'key', 'ckn']) + if conf.exists(['security', 'mka', 'ckn']): + macsec['security_mka_ckn'] = conf.return_value(['security', 'mka', 'ckn']) # Physical interface if conf.exists(['source-interface']): -- cgit v1.2.3 From 2417c2feedd62a59f0caa0c7a405c60e1f3be0e8 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Thu, 21 May 2020 15:06:16 +0200 Subject: macsec: T2023: support MACsec Key Agreement protocol actor priority --- data/templates/macsec/wpa_supplicant.conf.tmpl | 4 ++++ interface-definitions/interfaces-macsec.xml.in | 12 ++++++++++++ src/conf_mode/interfaces-macsec.py | 4 ++++ 3 files changed, 20 insertions(+) (limited to 'interface-definitions') diff --git a/data/templates/macsec/wpa_supplicant.conf.tmpl b/data/templates/macsec/wpa_supplicant.conf.tmpl index df7b6f153..eee215418 100644 --- a/data/templates/macsec/wpa_supplicant.conf.tmpl +++ b/data/templates/macsec/wpa_supplicant.conf.tmpl @@ -57,5 +57,9 @@ network={ # (2..64 hex-digits) mka_cak={{ security_mka_cak }} mka_ckn={{ security_mka_ckn }} + + # mka_priority (Priority of MKA Actor) is in 0..255 range with 255 being + # default priority + mka_priority={{ security_mka_priority }} } diff --git a/interface-definitions/interfaces-macsec.xml.in b/interface-definitions/interfaces-macsec.xml.in index 02e6e7b3f..af3971595 100644 --- a/interface-definitions/interfaces-macsec.xml.in +++ b/interface-definitions/interfaces-macsec.xml.in @@ -64,6 +64,18 @@ + + + Priority of MACsec Key Agreement protocol (MKA) actor (default: 255) + + 0-255 + MACsec Key Agreement protocol (MKA) priority + + + + + + diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py index 79c57d978..780ef9b5f 100755 --- a/src/conf_mode/interfaces-macsec.py +++ b/src/conf_mode/interfaces-macsec.py @@ -95,6 +95,10 @@ def get_config(): 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']) + # Physical interface if conf.exists(['source-interface']): macsec['source_interface'] = conf.return_value(['source-interface']) -- cgit v1.2.3