summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/add-pr-labels.yml1
-rw-r--r--.github/workflows/build-package.yml17
-rw-r--r--.github/workflows/chceck-pr-message.yml1
-rw-r--r--.github/workflows/check-unused-imports.yml1
-rw-r--r--.github/workflows/codeql.yml2
-rw-r--r--.github/workflows/package-smoketest.yml106
-rw-r--r--data/configd-include.json1
-rw-r--r--data/templates/firewall/nftables.j22
-rw-r--r--data/templates/system/40_usb_autosuspend.j25
-rw-r--r--interface-definitions/system_option.xml.in19
-rw-r--r--interface-definitions/vpn_openconnect.xml.in2
-rw-r--r--op-mode-definitions/restart-ssh.xml.in2
-rw-r--r--python/vyos/config_mgmt.py4
-rw-r--r--python/vyos/ifconfig/macsec.py2
-rw-r--r--python/vyos/utils/system.py32
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_macsec.py8
-rwxr-xr-xsrc/conf_mode/interfaces_macsec.py10
-rwxr-xr-xsrc/conf_mode/service_snmp.py28
-rwxr-xr-xsrc/conf_mode/system_option.py19
-rwxr-xr-xsrc/conf_mode/vpn_openconnect.py43
-rwxr-xr-xsrc/op_mode/powerctrl.py2
-rwxr-xr-xsrc/op_mode/uptime.py33
22 files changed, 249 insertions, 91 deletions
diff --git a/.github/workflows/add-pr-labels.yml b/.github/workflows/add-pr-labels.yml
index adef2b857..a7ee8446f 100644
--- a/.github/workflows/add-pr-labels.yml
+++ b/.github/workflows/add-pr-labels.yml
@@ -8,6 +8,7 @@ on:
- crux
- equuleus
- sagitta
+ - circinus
permissions:
pull-requests: write
diff --git a/.github/workflows/build-package.yml b/.github/workflows/build-package.yml
deleted file mode 100644
index 0200aceb4..000000000
--- a/.github/workflows/build-package.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Debian Package Build
-on:
- pull_request:
- branches:
- - current
-
-jobs:
- package-build:
- runs-on: ubuntu-latest
- container:
- image: vyos/vyos-build:current
- options: --sysctl net.ipv6.conf.lo.disable_ipv6=0
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Build Debian package
- run: dpkg-buildpackage -uc -us -tc -b
diff --git a/.github/workflows/chceck-pr-message.yml b/.github/workflows/chceck-pr-message.yml
index a9548f909..c567a5934 100644
--- a/.github/workflows/chceck-pr-message.yml
+++ b/.github/workflows/chceck-pr-message.yml
@@ -8,6 +8,7 @@ on:
- crux
- equuleus
- sagitta
+ - circinus
types: [opened, synchronize, edited]
permissions:
diff --git a/.github/workflows/check-unused-imports.yml b/.github/workflows/check-unused-imports.yml
index 835cc1180..322d4f3a8 100644
--- a/.github/workflows/check-unused-imports.yml
+++ b/.github/workflows/check-unused-imports.yml
@@ -5,6 +5,7 @@ on:
- current
- equuleus
- sagitta
+ - circinus
workflow_dispatch:
permissions:
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 3b654c0db..12654e42e 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -2,7 +2,7 @@ name: "Perform CodeQL Analysis"
on:
push:
- branches: [ "current", "sagitta", "equuleus" ]
+ branches: [ "current", "sagitta", "equuleus", "circinus" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "current" ]
diff --git a/.github/workflows/package-smoketest.yml b/.github/workflows/package-smoketest.yml
new file mode 100644
index 000000000..49bd91669
--- /dev/null
+++ b/.github/workflows/package-smoketest.yml
@@ -0,0 +1,106 @@
+name: Package ISO Test
+
+on:
+ pull_request:
+ branches:
+ - current
+
+jobs:
+ build:
+ runs-on: ubuntu-24.04
+ container:
+ image: vyos/vyos-build:current
+ options: --sysctl net.ipv6.conf.lo.disable_ipv6=0 --privileged
+ env:
+ BUILD_BY: autobuild@vyos.net
+ DEBIAN_MIRROR: http://deb.debian.org/debian/
+ outputs:
+ build_version: ${{ steps.version.outputs.build_version }}
+ steps:
+ - name: Clone vyos-build source code
+ uses: actions/checkout@v4
+ with:
+ repository: vyos/vyos-build
+ - name: Clone vyos-1x source code
+ uses: actions/checkout@v4
+ with:
+ repository: vyos/vyos-1x
+ path: packages/vyos-1x
+ fetch-tags: true # required for Debian package version
+ - name: Build vyos-1x package
+ run: |
+ cd packages/vyos-1x; dpkg-buildpackage -uc -us -tc -b
+ - name: Generate ISO version string
+ id: version
+ run: |
+ echo "build_version=1.5-integration-$(date -u +%Y%m%d%H%M)" >> $GITHUB_OUTPUT
+ - name: Build custom ISO image
+ run: |
+ sudo --preserve-env ./build-vyos-image \
+ --architecture amd64 \
+ --build-by $BUILD_BY \
+ --debian-mirror $DEBIAN_MIRROR \
+ --version ${{ steps.version.outputs.build_version }} \
+ --build-type release \
+ generic
+ - uses: actions/upload-artifact@v4
+ with:
+ name: vyos-${{ steps.version.outputs.build_version }}
+ path: build/live-image-amd64.hybrid.iso
+
+ cli-smoketests:
+ needs: build
+ runs-on: ubuntu-24.04
+ container:
+ image: vyos/vyos-build:current
+ options: --sysctl net.ipv6.conf.lo.disable_ipv6=0 --privileged
+ steps:
+ # We need the test script from vyos-build repo
+ - name: Clone vyos-build source code
+ uses: actions/checkout@v4
+ with:
+ repository: vyos/vyos-build
+ - uses: actions/download-artifact@v4
+ with:
+ name: vyos-${{ needs.build.outputs.build_version }}
+ path: build
+ - name: VyOS CLI smoketests
+ run: ls -al; ls -al build; sudo make test
+
+ config-load-tests:
+ needs: build
+ runs-on: ubuntu-24.04
+ container:
+ image: vyos/vyos-build:current
+ options: --sysctl net.ipv6.conf.lo.disable_ipv6=0 --privileged
+ steps:
+ # We need the test script from vyos-build repo
+ - name: Clone vyos-build source code
+ uses: actions/checkout@v4
+ with:
+ repository: vyos/vyos-build
+ - uses: actions/download-artifact@v4
+ with:
+ name: vyos-${{ needs.build.outputs.build_version }}
+ path: build
+ - name: VyOS config tests
+ run: sudo make testc
+
+ raid1-install-test:
+ needs: build
+ runs-on: ubuntu-24.04
+ container:
+ image: vyos/vyos-build:current
+ options: --sysctl net.ipv6.conf.lo.disable_ipv6=0 --privileged
+ steps:
+ # We need the test script from vyos-build repo
+ - name: Clone vyos-build source code
+ uses: actions/checkout@v4
+ with:
+ repository: vyos/vyos-build
+ - uses: actions/download-artifact@v4
+ with:
+ name: vyos-${{ needs.build.outputs.build_version }}
+ path: build
+ - name: VyOS RAID1 install test
+ run: sudo make testraid
diff --git a/data/configd-include.json b/data/configd-include.json
index 633d898a5..b92d58c72 100644
--- a/data/configd-include.json
+++ b/data/configd-include.json
@@ -79,6 +79,7 @@
"service_router-advert.py",
"service_salt-minion.py",
"service_sla.py",
+"service_snmp.py",
"service_ssh.py",
"service_tftp-server.py",
"service_webproxy.py",
diff --git a/data/templates/firewall/nftables.j2 b/data/templates/firewall/nftables.j2
index 343917fee..ee34f58fc 100644
--- a/data/templates/firewall/nftables.j2
+++ b/data/templates/firewall/nftables.j2
@@ -86,7 +86,7 @@ table ip vyos_filter {
{% for prior, conf in ipv4.output.items() %}
chain VYOS_OUTPUT_{{ prior }} {
type filter hook output priority {{ prior }}; policy accept;
-{% if global_options.state_policy is vyos_defined %}
+{% if global_options.state_policy is vyos_defined and prior == 'filter' %}
jump VYOS_STATE_POLICY
{% endif %}
{% if conf.rule is vyos_defined %}
diff --git a/data/templates/system/40_usb_autosuspend.j2 b/data/templates/system/40_usb_autosuspend.j2
new file mode 100644
index 000000000..01ba86420
--- /dev/null
+++ b/data/templates/system/40_usb_autosuspend.j2
@@ -0,0 +1,5 @@
+{% set autosuspend = "auto" %}
+{% if disable_usb_autosuspend is vyos_defined %}
+{% set autosuspend = "on" %}
+{% endif %}
+ACTION=="add", SUBSYSTEM=="usb", TEST=="power/control", ATTR{power/control}="{{ autosuspend }}"
diff --git a/interface-definitions/system_option.xml.in b/interface-definitions/system_option.xml.in
index fe517d17d..e78a53552 100644
--- a/interface-definitions/system_option.xml.in
+++ b/interface-definitions/system_option.xml.in
@@ -49,6 +49,19 @@
<valueless/>
</properties>
</leafNode>
+ <node name="debug">
+ <properties>
+ <help>Dynamic debugging for kernel module</help>
+ </properties>
+ <children>
+ <leafNode name="wireguard">
+ <properties>
+ <help>Dynamic debugging for Wireguard module</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
</children>
</node>
<leafNode name="keyboard-layout">
@@ -183,6 +196,12 @@
</properties>
<defaultValue>12-hour</defaultValue>
</leafNode>
+ <leafNode name="disable-usb-autosuspend">
+ <properties>
+ <help>Disable autosuspend for all USB devices</help>
+ <valueless/>
+ </properties>
+ </leafNode>
</children>
</node>
</children>
diff --git a/interface-definitions/vpn_openconnect.xml.in b/interface-definitions/vpn_openconnect.xml.in
index 7849d6886..a2f040b2f 100644
--- a/interface-definitions/vpn_openconnect.xml.in
+++ b/interface-definitions/vpn_openconnect.xml.in
@@ -275,7 +275,7 @@
<help>SSL Certificate, SSL Key and CA</help>
</properties>
<children>
- #include <include/pki/ca-certificate.xml.i>
+ #include <include/pki/ca-certificate-multi.xml.i>
#include <include/pki/certificate-key.xml.i>
</children>
</node>
diff --git a/op-mode-definitions/restart-ssh.xml.in b/op-mode-definitions/restart-ssh.xml.in
index 6504cc18a..543cafc24 100644
--- a/op-mode-definitions/restart-ssh.xml.in
+++ b/op-mode-definitions/restart-ssh.xml.in
@@ -6,7 +6,7 @@
<properties>
<help>Restart SSH service</help>
</properties>
- <command>if cli-shell-api existsActive service ssh; then sudo systemctl restart ssh.service; else echo "Service SSH not configured"; fi</command>
+ <command>if cli-shell-api existsActive service ssh; then sudo systemctl restart "ssh@*.service"; else echo "Service SSH not configured"; fi</command>
</node>
</children>
</node>
diff --git a/python/vyos/config_mgmt.py b/python/vyos/config_mgmt.py
index 70b6ea203..d518737ca 100644
--- a/python/vyos/config_mgmt.py
+++ b/python/vyos/config_mgmt.py
@@ -81,9 +81,11 @@ def save_config(target, json_out=None):
if rc != 0:
logger.critical(f'save config failed: {out}')
-def unsaved_commits() -> bool:
+def unsaved_commits(allow_missing_config=False) -> bool:
if get_full_version_data()['boot_via'] == 'livecd':
return False
+ if allow_missing_config and not os.path.exists(config_file):
+ return True
tmp_save = '/tmp/config.running'
save_config(tmp_save)
ret = not cmp(tmp_save, config_file, shallow=False)
diff --git a/python/vyos/ifconfig/macsec.py b/python/vyos/ifconfig/macsec.py
index bde1d9aec..383905814 100644
--- a/python/vyos/ifconfig/macsec.py
+++ b/python/vyos/ifconfig/macsec.py
@@ -66,7 +66,7 @@ class MACsecIf(Interface):
cmd = 'ip macsec add {ifname} rx port 1 address'.format(**self.config)
cmd += f' {peer_config["mac"]}'
self._cmd(cmd)
- # Add the rx-key to the address
+ # Add the encryption key to the address
cmd += f' sa 0 pn 1 on key 01 {peer_config["key"]}'
self._cmd(cmd)
diff --git a/python/vyos/utils/system.py b/python/vyos/utils/system.py
index 55813a5f7..f427032a4 100644
--- a/python/vyos/utils/system.py
+++ b/python/vyos/utils/system.py
@@ -1,4 +1,4 @@
-# Copyright 2023 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2023-2024 VyOS maintainers and contributors <maintainers@vyos.io>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -98,3 +98,33 @@ def load_as_module(name: str, path: str):
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
+
+def get_uptime_seconds():
+ """ Returns system uptime in seconds """
+ from re import search
+ from vyos.utils.file import read_file
+
+ data = read_file("/proc/uptime")
+ seconds = search(r"([0-9\.]+)\s", data).group(1)
+ res = int(float(seconds))
+
+ return res
+
+def get_load_averages():
+ """ Returns load averages for 1, 5, and 15 minutes as a dict """
+ from re import search
+ from vyos.utils.file import read_file
+ from vyos.utils.cpu import get_core_count
+
+ data = read_file("/proc/loadavg")
+ matches = search(r"\s*(?P<one>[0-9\.]+)\s+(?P<five>[0-9\.]+)\s+(?P<fifteen>[0-9\.]+)\s*", data)
+
+ core_count = get_core_count()
+
+ res = {}
+ res[1] = float(matches["one"]) / core_count
+ res[5] = float(matches["five"]) / core_count
+ res[15] = float(matches["fifteen"]) / core_count
+
+ return res
+
diff --git a/smoketest/scripts/cli/test_interfaces_macsec.py b/smoketest/scripts/cli/test_interfaces_macsec.py
index a4e6840ca..d73895b7f 100755
--- a/smoketest/scripts/cli/test_interfaces_macsec.py
+++ b/smoketest/scripts/cli/test_interfaces_macsec.py
@@ -225,11 +225,11 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase):
self.cli_commit()
self.cli_delete(self._base_path + [interface, 'security', 'mka'])
- # check validate() - tx-key required
+ # check validate() - key required
with self.assertRaises(ConfigSessionError):
self.cli_commit()
- # check validate() - tx-key length must match cipher
+ # check validate() - key length must match cipher
self.cli_set(self._base_path + [interface, 'security', 'static', 'key', tx_key_2])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
@@ -239,7 +239,7 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase):
with self.assertRaises(ConfigSessionError):
self.cli_commit()
- # check validate() - enabled peer must have both rx-key and MAC defined
+ # check validate() - enabled peer must have both key and MAC defined
self.cli_set(self._base_path + [interface, 'security', 'static', 'peer', 'TESTPEER'])
with self.assertRaises(ConfigSessionError):
self.cli_commit()
@@ -252,7 +252,7 @@ class MACsecInterfaceTest(BasicInterfaceTest.TestCase):
self.cli_commit()
self.cli_set(self._base_path + [interface, 'security', 'static', 'peer', 'TESTPEER', 'mac', peer_mac])
- # check validate() - peer rx-key length must match cipher
+ # check validate() - peer key length must match cipher
self.cli_set(self._base_path + [interface, 'security', 'cipher', cipher2])
self.cli_set(self._base_path + [interface, 'security', 'static', 'key', tx_key_2])
with self.assertRaises(ConfigSessionError):
diff --git a/src/conf_mode/interfaces_macsec.py b/src/conf_mode/interfaces_macsec.py
index eb0ca9a8b..3ede4377a 100755
--- a/src/conf_mode/interfaces_macsec.py
+++ b/src/conf_mode/interfaces_macsec.py
@@ -103,9 +103,9 @@ def verify(macsec):
# Logic to check static configuration
if dict_search('security.static', macsec) != None:
- # tx-key must be defined
+ # key must be defined
if dict_search('security.static.key', macsec) == None:
- raise ConfigError('Static MACsec tx-key must be defined.')
+ raise ConfigError('Static MACsec key must be defined.')
tx_len = len(dict_search('security.static.key', macsec))
@@ -119,12 +119,12 @@ def verify(macsec):
if 'peer' not in macsec['security']['static']:
raise ConfigError('Must have at least one peer defined for static MACsec')
- # For every enabled peer, make sure a MAC and rx-key is defined
+ # For every enabled peer, make sure a MAC and key is defined
for peer, peer_config in macsec['security']['static']['peer'].items():
if 'disable' not in peer_config and ('mac' not in peer_config or 'key' not in peer_config):
- raise ConfigError('Every enabled MACsec static peer must have a MAC address and rx-key defined.')
+ raise ConfigError('Every enabled MACsec static peer must have a MAC address and key defined!')
- # check rx-key length against cipher suite
+ # check key length against cipher suite
rx_len = len(peer_config['key'])
if dict_search('security.cipher', macsec) == 'gcm-aes-128' and rx_len != GCM_AES_128_LEN:
diff --git a/src/conf_mode/service_snmp.py b/src/conf_mode/service_snmp.py
index 6565ffd60..6f025cc23 100755
--- a/src/conf_mode/service_snmp.py
+++ b/src/conf_mode/service_snmp.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2023 VyOS maintainers and contributors
+# Copyright (C) 2018-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
@@ -26,10 +26,12 @@ from vyos.snmpv3_hashgen import plaintext_to_md5
from vyos.snmpv3_hashgen import plaintext_to_sha1
from vyos.snmpv3_hashgen import random
from vyos.template import render
-from vyos.utils.process import call
-from vyos.utils.permission import chmod_755
+from vyos.utils.configfs import delete_cli_node
+from vyos.utils.configfs import add_cli_node
from vyos.utils.dict import dict_search
from vyos.utils.network import is_addr_assigned
+from vyos.utils.process import call
+from vyos.utils.permission import chmod_755
from vyos.version import get_version_data
from vyos import ConfigError
from vyos import airbag
@@ -192,12 +194,8 @@ def generate(snmp):
return None
if 'v3' in snmp:
- # net-snmp is now regenerating the configuration file in the background
- # thus we need to re-open and re-read the file as the content changed.
- # After that we can no read the encrypted password from the config and
- # replace the CLI plaintext password with its encrypted version.
- os.environ['vyos_libexec_dir'] = '/usr/libexec/vyos'
-
+ # SNMPv3 uses a hashed password. If CLI defines a plaintext password,
+ # we will hash it in the background and replace the CLI node!
if 'user' in snmp['v3']:
for user, user_config in snmp['v3']['user'].items():
if dict_search('auth.type', user_config) == 'sha':
@@ -212,8 +210,9 @@ def generate(snmp):
snmp['v3']['user'][user]['auth']['encrypted_password'] = tmp
del snmp['v3']['user'][user]['auth']['plaintext_password']
- call(f'/opt/vyatta/sbin/my_set service snmp v3 user "{user}" auth encrypted-password "{tmp}" > /dev/null')
- call(f'/opt/vyatta/sbin/my_delete service snmp v3 user "{user}" auth plaintext-password > /dev/null')
+ cli_base = ['service', 'snmp', 'v3', 'user', user, 'auth']
+ delete_cli_node(cli_base + ['plaintext-password'])
+ add_cli_node(cli_base + ['encrypted-password'], value=tmp)
if dict_search('privacy.plaintext_password', user_config) is not None:
tmp = hash(dict_search('privacy.plaintext_password', user_config),
@@ -222,8 +221,9 @@ def generate(snmp):
snmp['v3']['user'][user]['privacy']['encrypted_password'] = tmp
del snmp['v3']['user'][user]['privacy']['plaintext_password']
- call(f'/opt/vyatta/sbin/my_set service snmp v3 user "{user}" privacy encrypted-password "{tmp}" > /dev/null')
- call(f'/opt/vyatta/sbin/my_delete service snmp v3 user "{user}" privacy plaintext-password > /dev/null')
+ cli_base = ['service', 'snmp', 'v3', 'user', user, 'privacy']
+ delete_cli_node(cli_base + ['plaintext-password'])
+ add_cli_node(cli_base + ['encrypted-password'], value=tmp)
# Write client config file
render(config_file_client, 'snmp/etc.snmp.conf.j2', snmp)
@@ -246,7 +246,7 @@ def apply(snmp):
return None
# start SNMP daemon
- call(f'systemctl restart {systemd_service}')
+ call(f'systemctl reload-or-restart {systemd_service}')
# Enable AgentX in FRR
# This should be done for each daemon individually because common command
diff --git a/src/conf_mode/system_option.py b/src/conf_mode/system_option.py
index a2e5db575..571ce55ec 100755
--- a/src/conf_mode/system_option.py
+++ b/src/conf_mode/system_option.py
@@ -24,6 +24,9 @@ from vyos.configverify import verify_source_interface
from vyos.configverify import verify_interface_exists
from vyos.system import grub_util
from vyos.template import render
+from vyos.utils.dict import dict_search
+from vyos.utils.file import write_file
+from vyos.utils.kernel import check_kmod
from vyos.utils.process import cmd
from vyos.utils.process import is_systemd_service_running
from vyos.utils.network import is_addr_assigned
@@ -35,6 +38,8 @@ airbag.enable()
curlrc_config = r'/etc/curlrc'
ssh_config = r'/etc/ssh/ssh_config.d/91-vyos-ssh-client-options.conf'
systemd_action_file = '/lib/systemd/system/ctrl-alt-del.target'
+usb_autosuspend = r'/etc/udev/rules.d/40-usb-autosuspend.rules'
+kernel_dynamic_debug = r'/sys/kernel/debug/dynamic_debug/control'
time_format_to_locale = {
'12-hour': 'en_US.UTF-8',
'24-hour': 'en_GB.UTF-8'
@@ -85,6 +90,7 @@ def verify(options):
def generate(options):
render(curlrc_config, 'system/curlrc.j2', options)
render(ssh_config, 'system/ssh_config.j2', options)
+ render(usb_autosuspend, 'system/40_usb_autosuspend.j2', options)
cmdline_options = []
if 'kernel' in options:
@@ -155,6 +161,19 @@ def apply(options):
time_format = time_format_to_locale.get(options['time_format'])
cmd(f'localectl set-locale LC_TIME={time_format}')
+ # Reload UDEV, required for USB auto suspend
+ cmd('udevadm control --reload-rules')
+
+ # Enable/disable dynamic debugging for kernel modules
+ modules = ['wireguard']
+ modules_enabled = dict_search('kernel.debug', options) or []
+ for module in modules:
+ if module in modules_enabled:
+ check_kmod(module)
+ write_file(kernel_dynamic_debug, f'module {module} +p')
+ else:
+ write_file(kernel_dynamic_debug, f'module {module} -p')
+
if __name__ == '__main__':
try:
c = get_config()
diff --git a/src/conf_mode/vpn_openconnect.py b/src/conf_mode/vpn_openconnect.py
index 8159fedea..42785134f 100755
--- a/src/conf_mode/vpn_openconnect.py
+++ b/src/conf_mode/vpn_openconnect.py
@@ -21,14 +21,17 @@ from vyos.base import Warning
from vyos.config import Config
from vyos.configverify import verify_pki_certificate
from vyos.configverify import verify_pki_ca_certificate
-from vyos.pki import wrap_certificate
+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.utils.process import call
+from vyos.utils.dict import dict_search
+from vyos.utils.file import write_file
from vyos.utils.network import check_port_availability
-from vyos.utils.process import is_systemd_service_running
from vyos.utils.network import is_listen_port_bind_service
-from vyos.utils.dict import dict_search
+from vyos.utils.process import call
+from vyos.utils.process import is_systemd_service_running
from vyos import ConfigError
from passlib.hash import sha512_crypt
from time import sleep
@@ -142,7 +145,8 @@ def verify(ocserv):
verify_pki_certificate(ocserv, ocserv['ssl']['certificate'])
if 'ca_certificate' in ocserv['ssl']:
- verify_pki_ca_certificate(ocserv, ocserv['ssl']['ca_certificate'])
+ for ca_cert in ocserv['ssl']['ca_certificate']:
+ verify_pki_ca_certificate(ocserv, ca_cert)
# Check network settings
if "network_settings" in ocserv:
@@ -219,25 +223,36 @@ def generate(ocserv):
if "ssl" in ocserv:
cert_file_path = os.path.join(cfg_dir, 'cert.pem')
cert_key_path = os.path.join(cfg_dir, 'cert.key')
- ca_cert_file_path = os.path.join(cfg_dir, 'ca.pem')
+
if 'certificate' in ocserv['ssl']:
cert_name = ocserv['ssl']['certificate']
pki_cert = ocserv['pki']['certificate'][cert_name]
- with open(cert_file_path, 'w') as f:
- f.write(wrap_certificate(pki_cert['certificate']))
+ loaded_pki_cert = load_certificate(pki_cert['certificate'])
+ loaded_ca_certs = {load_certificate(c['certificate'])
+ for c in ocserv['pki']['ca'].values()} if 'ca' in ocserv['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))
if 'private' in pki_cert and 'key' in pki_cert['private']:
- with open(cert_key_path, 'w') as f:
- f.write(wrap_private_key(pki_cert['private']['key']))
+ write_file(cert_key_path, wrap_private_key(pki_cert['private']['key']))
if 'ca_certificate' in ocserv['ssl']:
- ca_name = ocserv['ssl']['ca_certificate']
- pki_ca_cert = ocserv['pki']['ca'][ca_name]
+ ca_cert_file_path = os.path.join(cfg_dir, 'ca.pem')
+ ca_chains = []
+
+ for ca_name in ocserv['ssl']['ca_certificate']:
+ pki_ca_cert = ocserv['pki']['ca'][ca_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))
- with open(ca_cert_file_path, 'w') as f:
- f.write(wrap_certificate(pki_ca_cert['certificate']))
+ write_file(ca_cert_file_path, '\n'.join(ca_chains))
# Render config
render(ocserv_conf, 'ocserv/ocserv_config.j2', ocserv)
diff --git a/src/op_mode/powerctrl.py b/src/op_mode/powerctrl.py
index 6c8f802b5..cb4a175dd 100755
--- a/src/op_mode/powerctrl.py
+++ b/src/op_mode/powerctrl.py
@@ -110,7 +110,7 @@ def check_unsaved_config():
from vyos.config_mgmt import unsaved_commits
from vyos.utils.boot import boot_configuration_success
- if unsaved_commits() and boot_configuration_success():
+ if unsaved_commits(allow_missing_config=True) and boot_configuration_success():
print("Warning: there are unsaved configuration changes!")
print("Run 'save' command if you do not want to lose those changes after reboot/shutdown.")
else:
diff --git a/src/op_mode/uptime.py b/src/op_mode/uptime.py
index 559eed24c..1c1a149ec 100755
--- a/src/op_mode/uptime.py
+++ b/src/op_mode/uptime.py
@@ -18,39 +18,14 @@ import sys
import vyos.opmode
-def _get_uptime_seconds():
- from re import search
- from vyos.utils.file import read_file
-
- data = read_file("/proc/uptime")
- seconds = search("([0-9\.]+)\s", data).group(1)
-
- return int(float(seconds))
-
-def _get_load_averages():
- from re import search
- from vyos.utils.cpu import get_core_count
- from vyos.utils.process import cmd
-
- data = cmd("uptime")
- matches = search(r"load average:\s*(?P<one>[0-9\.]+)\s*,\s*(?P<five>[0-9\.]+)\s*,\s*(?P<fifteen>[0-9\.]+)\s*", data)
-
- core_count = get_core_count()
-
- res = {}
- res[1] = float(matches["one"]) / core_count
- res[5] = float(matches["five"]) / core_count
- res[15] = float(matches["fifteen"]) / core_count
-
- return res
-
def _get_raw_data():
+ from vyos.utils.system import get_uptime_seconds, get_load_averages
from vyos.utils.convert import seconds_to_human
res = {}
- res["uptime_seconds"] = _get_uptime_seconds()
- res["uptime"] = seconds_to_human(_get_uptime_seconds(), separator=' ')
- res["load_average"] = _get_load_averages()
+ uptime_seconds = get_uptime_seconds()
+ res["uptime"] = seconds_to_human(uptime_seconds, separator=' ')
+ res["load_average"] = get_load_averages()
return res