diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/activation-scripts/20-ethernet_offload.py | 13 | ||||
-rwxr-xr-x | src/conf_mode/interfaces_bonding.py | 4 | ||||
-rwxr-xr-x | src/conf_mode/interfaces_ethernet.py | 78 | ||||
-rwxr-xr-x | src/conf_mode/policy.py | 8 | ||||
-rw-r--r-- | src/etc/sudoers.d/vyos | 3 | ||||
-rwxr-xr-x | src/op_mode/secure_boot.py | 50 | ||||
-rwxr-xr-x | src/op_mode/version.py | 9 | ||||
-rwxr-xr-x | src/op_mode/vpn_ike_sa.py | 2 |
8 files changed, 80 insertions, 87 deletions
diff --git a/src/activation-scripts/20-ethernet_offload.py b/src/activation-scripts/20-ethernet_offload.py index 33b0ea469..ca7213512 100755 --- a/src/activation-scripts/20-ethernet_offload.py +++ b/src/activation-scripts/20-ethernet_offload.py @@ -17,9 +17,12 @@ # CLI. See https://vyos.dev/T3619#102254 for all the details. # T3787: Remove deprecated UDP fragmentation offloading option # T6006: add to activation-scripts: migration-scripts/interfaces/20-to-21 +# T6716: Honor the configured offload settings and don't automatically add +# them to the config if the kernel has them set (unless its a live boot) from vyos.ethtool import Ethtool from vyos.configtree import ConfigTree +from vyos.system.image import is_live_boot def activate(config: ConfigTree): base = ['interfaces', 'ethernet'] @@ -36,7 +39,7 @@ def activate(config: ConfigTree): enabled, fixed = eth.get_generic_receive_offload() if configured and fixed: config.delete(base + [ifname, 'offload', 'gro']) - elif enabled and not fixed: + elif is_live_boot() and enabled and not fixed: config.set(base + [ifname, 'offload', 'gro']) # If GSO is enabled by the Kernel - we reflect this on the CLI. If GSO is @@ -45,7 +48,7 @@ def activate(config: ConfigTree): enabled, fixed = eth.get_generic_segmentation_offload() if configured and fixed: config.delete(base + [ifname, 'offload', 'gso']) - elif enabled and not fixed: + elif is_live_boot() and enabled and not fixed: config.set(base + [ifname, 'offload', 'gso']) # If LRO is enabled by the Kernel - we reflect this on the CLI. If LRO is @@ -54,7 +57,7 @@ def activate(config: ConfigTree): enabled, fixed = eth.get_large_receive_offload() if configured and fixed: config.delete(base + [ifname, 'offload', 'lro']) - elif enabled and not fixed: + elif is_live_boot() and enabled and not fixed: config.set(base + [ifname, 'offload', 'lro']) # If SG is enabled by the Kernel - we reflect this on the CLI. If SG is @@ -63,7 +66,7 @@ def activate(config: ConfigTree): enabled, fixed = eth.get_scatter_gather() if configured and fixed: config.delete(base + [ifname, 'offload', 'sg']) - elif enabled and not fixed: + elif is_live_boot() and enabled and not fixed: config.set(base + [ifname, 'offload', 'sg']) # If TSO is enabled by the Kernel - we reflect this on the CLI. If TSO is @@ -72,7 +75,7 @@ def activate(config: ConfigTree): enabled, fixed = eth.get_tcp_segmentation_offload() if configured and fixed: config.delete(base + [ifname, 'offload', 'tso']) - elif enabled and not fixed: + elif is_live_boot() and enabled and not fixed: config.set(base + [ifname, 'offload', 'tso']) # Remove deprecated UDP fragmentation offloading option diff --git a/src/conf_mode/interfaces_bonding.py b/src/conf_mode/interfaces_bonding.py index 5e5d5fba1..bbbfb0385 100755 --- a/src/conf_mode/interfaces_bonding.py +++ b/src/conf_mode/interfaces_bonding.py @@ -25,6 +25,7 @@ from vyos.configdict import is_source_interface from vyos.configverify import verify_address from vyos.configverify import verify_bridge_delete from vyos.configverify import verify_dhcpv6 +from vyos.configverify import verify_eapol from vyos.configverify import verify_mirror_redirect from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_vlan_config @@ -73,7 +74,7 @@ def get_config(config=None): else: conf = Config() base = ['interfaces', 'bonding'] - ifname, bond = get_interface_dict(conf, base) + ifname, bond = get_interface_dict(conf, base, with_pki=True) # To make our own life easier transfor the list of member interfaces # into a dictionary - we will use this to add additional information @@ -196,6 +197,7 @@ def verify(bond): verify_dhcpv6(bond) verify_vrf(bond) verify_mirror_redirect(bond) + verify_eapol(bond) # use common function to verify VLAN configuration verify_vlan_config(bond) diff --git a/src/conf_mode/interfaces_ethernet.py b/src/conf_mode/interfaces_ethernet.py index afc48ead8..34ce7bc47 100755 --- a/src/conf_mode/interfaces_ethernet.py +++ b/src/conf_mode/interfaces_ethernet.py @@ -31,32 +31,20 @@ from vyos.configverify import verify_mtu_ipv6 from vyos.configverify import verify_vlan_config from vyos.configverify import verify_vrf from vyos.configverify import verify_bond_bridge_member -from vyos.configverify import verify_pki_certificate -from vyos.configverify import verify_pki_ca_certificate +from vyos.configverify import verify_eapol from vyos.ethtool import Ethtool from vyos.ifconfig import EthernetIf from vyos.ifconfig import BondIf -from vyos.pki import find_chain -from vyos.pki import encode_certificate -from vyos.pki import load_certificate -from vyos.pki import wrap_private_key -from vyos.template import render from vyos.template import render_to_string -from vyos.utils.process import call from vyos.utils.dict import dict_search from vyos.utils.dict import dict_to_paths_values from vyos.utils.dict import dict_set from vyos.utils.dict import dict_delete -from vyos.utils.file import write_file from vyos import ConfigError from vyos import frr from vyos import airbag airbag.enable() -# XXX: wpa_supplicant works on the source interface -cfg_dir = '/run/wpa_supplicant' -wpa_suppl_conf = '/run/wpa_supplicant/{ifname}.conf' - def update_bond_options(conf: Config, eth_conf: dict) -> list: """ Return list of blocked options if interface is a bond member @@ -277,23 +265,6 @@ def verify_allowedbond_changes(ethernet: dict): f' on interface "{ethernet["ifname"]}".' \ f' Interface is a bond member') -def verify_eapol(ethernet: dict): - """ - Common helper function used by interface implementations to perform - recurring validation of EAPoL configuration. - """ - if 'eapol' not in ethernet: - return - - if 'certificate' not in ethernet['eapol']: - raise ConfigError('Certificate must be specified when using EAPoL!') - - verify_pki_certificate(ethernet, ethernet['eapol']['certificate'], no_password_protected=True) - - if 'ca_certificate' in ethernet['eapol']: - for ca_cert in ethernet['eapol']['ca_certificate']: - verify_pki_ca_certificate(ethernet, ca_cert) - def verify(ethernet): if 'deleted' in ethernet: return None @@ -346,51 +317,10 @@ def verify_ethernet(ethernet): verify_vlan_config(ethernet) return None - def generate(ethernet): - # render real configuration file once - wpa_supplicant_conf = wpa_suppl_conf.format(**ethernet) - if 'deleted' in ethernet: - # delete configuration on interface removal - if os.path.isfile(wpa_supplicant_conf): - os.unlink(wpa_supplicant_conf) return None - if 'eapol' in ethernet: - ifname = ethernet['ifname'] - - render(wpa_supplicant_conf, 'ethernet/wpa_supplicant.conf.j2', ethernet) - - cert_file_path = os.path.join(cfg_dir, f'{ifname}_cert.pem') - cert_key_path = os.path.join(cfg_dir, f'{ifname}_cert.key') - - cert_name = ethernet['eapol']['certificate'] - pki_cert = ethernet['pki']['certificate'][cert_name] - - loaded_pki_cert = load_certificate(pki_cert['certificate']) - loaded_ca_certs = {load_certificate(c['certificate']) - for c in ethernet['pki']['ca'].values()} if 'ca' in ethernet['pki'] else {} - - cert_full_chain = find_chain(loaded_pki_cert, loaded_ca_certs) - - write_file(cert_file_path, - '\n'.join(encode_certificate(c) for c in cert_full_chain)) - write_file(cert_key_path, wrap_private_key(pki_cert['private']['key'])) - - if 'ca_certificate' in ethernet['eapol']: - ca_cert_file_path = os.path.join(cfg_dir, f'{ifname}_ca.pem') - ca_chains = [] - - for ca_cert_name in ethernet['eapol']['ca_certificate']: - pki_ca_cert = ethernet['pki']['ca'][ca_cert_name] - loaded_ca_cert = load_certificate(pki_ca_cert['certificate']) - ca_full_chain = find_chain(loaded_ca_cert, loaded_ca_certs) - ca_chains.append( - '\n'.join(encode_certificate(c) for c in ca_full_chain)) - - write_file(ca_cert_file_path, '\n'.join(ca_chains)) - ethernet['frr_zebra_config'] = '' if 'deleted' not in ethernet: ethernet['frr_zebra_config'] = render_to_string('frr/evpn.mh.frr.j2', ethernet) @@ -399,8 +329,6 @@ def generate(ethernet): def apply(ethernet): ifname = ethernet['ifname'] - # take care about EAPoL supplicant daemon - eapol_action='stop' e = EthernetIf(ifname) if 'deleted' in ethernet: @@ -408,10 +336,6 @@ def apply(ethernet): e.remove() else: e.update(ethernet) - if 'eapol' in ethernet: - eapol_action='reload-or-restart' - - call(f'systemctl {eapol_action} wpa_supplicant-wired@{ifname}') zebra_daemon = 'zebra' # Save original configuration prior to starting any commit actions diff --git a/src/conf_mode/policy.py b/src/conf_mode/policy.py index 4df893ebf..a5963e72c 100755 --- a/src/conf_mode/policy.py +++ b/src/conf_mode/policy.py @@ -167,10 +167,10 @@ def verify(policy): continue for rule, rule_config in route_map_config['rule'].items(): - # Action 'deny' cannot be used with "continue" - # FRR does not validate it T4827 - if rule_config['action'] == 'deny' and 'continue' in rule_config: - raise ConfigError(f'rule {rule} "continue" cannot be used with action deny!') + # Action 'deny' cannot be used with "continue" or "on-match" + # FRR does not validate it T4827, T6676 + if rule_config['action'] == 'deny' and ('continue' in rule_config or 'on_match' in rule_config): + raise ConfigError(f'rule {rule} "continue" or "on-match" cannot be used with action deny!') # Specified community-list must exist tmp = dict_search('match.community.community_list', diff --git a/src/etc/sudoers.d/vyos b/src/etc/sudoers.d/vyos index 63a944f41..67d7babc4 100644 --- a/src/etc/sudoers.d/vyos +++ b/src/etc/sudoers.d/vyos @@ -57,4 +57,7 @@ Cmnd_Alias KEA_IP6_ROUTES = /sbin/ip -6 route replace *,\ # Allow members of group sudo to execute any command %sudo ALL=NOPASSWD: ALL +# Allow any user to query Machine Owner Key status +%sudo ALL=NOPASSWD: /usr/bin/mokutil + _kea ALL=NOPASSWD: KEA_IP6_ROUTES diff --git a/src/op_mode/secure_boot.py b/src/op_mode/secure_boot.py new file mode 100755 index 000000000..5f6390a15 --- /dev/null +++ b/src/op_mode/secure_boot.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 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 <http://www.gnu.org/licenses/>. + +import sys +import vyos.opmode + +from vyos.utils.boot import is_uefi_system +from vyos.utils.system import get_secure_boot_state + +def _get_raw_data(name=None): + sb_data = { + 'state' : get_secure_boot_state(), + 'uefi' : is_uefi_system() + } + return sb_data + +def _get_formatted_output(raw_data): + if not raw_data['uefi']: + print('System run in legacy BIOS mode!') + state = 'enabled' if raw_data['state'] else 'disabled' + return f'SecureBoot {state}' + +def show(raw: bool): + sb_data = _get_raw_data() + if raw: + return sb_data + else: + return _get_formatted_output(sb_data) + +if __name__ == "__main__": + try: + res = vyos.opmode.run(sys.modules[__name__]) + if res: + print(res) + except (ValueError, vyos.opmode.Error) as e: + print(e) + sys.exit(1) diff --git a/src/op_mode/version.py b/src/op_mode/version.py index 09d69ad1d..71a40dd50 100755 --- a/src/op_mode/version.py +++ b/src/op_mode/version.py @@ -25,6 +25,9 @@ import vyos.opmode import vyos.version import vyos.limericks +from vyos.utils.boot import is_uefi_system +from vyos.utils.system import get_secure_boot_state + from jinja2 import Template version_output_tmpl = """ @@ -43,6 +46,7 @@ Build comment: {{build_comment}} Architecture: {{system_arch}} Boot via: {{boot_via}} System type: {{system_type}} +Secure Boot: {{secure_boot}} Hardware vendor: {{hardware_vendor}} Hardware model: {{hardware_model}} @@ -57,6 +61,11 @@ Copyright: VyOS maintainers and contributors def _get_raw_data(funny=False): version_data = vyos.version.get_full_version_data() + version_data["secure_boot"] = "n/a (BIOS)" + if is_uefi_system(): + version_data["secure_boot"] = "disabled" + if get_secure_boot_state(): + version_data["secure_boot"] = "enabled" if funny: version_data["limerick"] = vyos.limericks.get_random() diff --git a/src/op_mode/vpn_ike_sa.py b/src/op_mode/vpn_ike_sa.py index 5e2aaae6b..9385bcd0c 100755 --- a/src/op_mode/vpn_ike_sa.py +++ b/src/op_mode/vpn_ike_sa.py @@ -38,6 +38,8 @@ def ike_sa(peer, nat): peers = [] for conn in sas: for name, sa in conn.items(): + if peer and s(sa['remote-host']) != peer: + continue if name.startswith('peer_') and name in peers: continue if nat and 'nat-local' not in sa: |