diff options
-rw-r--r-- | .github/workflows/mergifyio_backport.yml | 2 | ||||
-rw-r--r-- | .github/workflows/pull-request-labels.yml | 4 | ||||
-rw-r--r-- | data/templates/ipsec/swanctl/remote_access.j2 | 2 | ||||
-rw-r--r-- | data/templates/load-balancing/haproxy.cfg.j2 | 12 | ||||
-rw-r--r-- | interface-definitions/include/accel-ppp/radius-additions.xml.i | 2 | ||||
-rw-r--r-- | interface-definitions/include/haproxy/tcp-request.xml.i | 22 | ||||
-rw-r--r-- | interface-definitions/load-balancing_reverse-proxy.xml.in | 1 | ||||
-rw-r--r-- | interface-definitions/vpn_ipsec.xml.in | 20 | ||||
-rw-r--r-- | python/vyos/utils/convert.py | 23 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_load-balancing_reverse-proxy.py | 113 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_vpn_ipsec.py | 5 | ||||
-rw-r--r-- | src/etc/rsyslog.conf | 30 | ||||
-rwxr-xr-x | src/helpers/vyos-vrrp-conntracksync.sh | 4 | ||||
-rwxr-xr-x | src/op_mode/connect_disconnect.py | 6 | ||||
-rwxr-xr-x | src/op_mode/image_installer.py | 11 | ||||
-rwxr-xr-x | src/op_mode/uptime.py | 2 |
16 files changed, 191 insertions, 68 deletions
diff --git a/.github/workflows/mergifyio_backport.yml b/.github/workflows/mergifyio_backport.yml index f1f4312c4..d9f863d9a 100644 --- a/.github/workflows/mergifyio_backport.yml +++ b/.github/workflows/mergifyio_backport.yml @@ -13,7 +13,7 @@ jobs: id: regex-match with: text: ${{ github.event.comment.body }} - regex: '[Mm]ergifyio backport ' + regex: '@[Mm][Ee][Rr][Gg][Ii][Ff][Yy][Ii][Oo] backport ' - uses: actions-ecosystem/action-add-labels@v1 if: ${{ steps.regex-match.outputs.match != '' }} diff --git a/.github/workflows/pull-request-labels.yml b/.github/workflows/pull-request-labels.yml index 3398af5b0..43856beaa 100644 --- a/.github/workflows/pull-request-labels.yml +++ b/.github/workflows/pull-request-labels.yml @@ -12,9 +12,9 @@ on: jobs: add-pr-label: name: Add PR Labels - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - - uses: actions/labeler@v5.0.0 + - uses: actions/labeler@v5 diff --git a/data/templates/ipsec/swanctl/remote_access.j2 b/data/templates/ipsec/swanctl/remote_access.j2 index adfa32bde..6bced88c7 100644 --- a/data/templates/ipsec/swanctl/remote_access.j2 +++ b/data/templates/ipsec/swanctl/remote_access.j2 @@ -33,7 +33,7 @@ auth = pubkey {% elif rw_conf.authentication.client_mode.startswith("eap") %} auth = {{ rw_conf.authentication.client_mode }} - eap_id = %any + eap_id = {{ '%any' if rw_conf.authentication.eap_id == 'any' else rw_conf.authentication.eap_id }} {% endif %} {% if rw_conf.authentication.client_mode is vyos_defined('eap-tls') or rw_conf.authentication.client_mode is vyos_defined('x509') %} {# pass all configured CAs as filenames, separated by commas #} diff --git a/data/templates/load-balancing/haproxy.cfg.j2 b/data/templates/load-balancing/haproxy.cfg.j2 index dd93afba5..e8622ba7b 100644 --- a/data/templates/load-balancing/haproxy.cfg.j2 +++ b/data/templates/load-balancing/haproxy.cfg.j2 @@ -69,6 +69,18 @@ frontend {{ front }} {% endif %} {% if front_config.mode is vyos_defined %} mode {{ front_config.mode }} +{% if front_config.tcp_request.inspect_delay is vyos_defined %} + tcp-request inspect-delay {{ front_config.tcp_request.inspect_delay }} +{% endif %} +{# add tcp-request related directive if ssl is configed #} +{% if front_config.mode is vyos_defined('tcp') and front_config.rule is vyos_defined %} +{% for rule, rule_config in front_config.rule.items() %} +{% if rule_config.ssl is vyos_defined %} + tcp-request content accept if { req_ssl_hello_type 1 } +{% break %} +{% endif %} +{% endfor %} +{% endif %} {% endif %} {% if front_config.rule is vyos_defined %} {% for rule, rule_config in front_config.rule.items() %} diff --git a/interface-definitions/include/accel-ppp/radius-additions.xml.i b/interface-definitions/include/accel-ppp/radius-additions.xml.i index cdd0bf300..3c2eb09eb 100644 --- a/interface-definitions/include/accel-ppp/radius-additions.xml.i +++ b/interface-definitions/include/accel-ppp/radius-additions.xml.i @@ -122,7 +122,7 @@ </constraint> <valueHelp> <format>ipv4</format> - <description>IPv4 address for aynamic authorization server</description> + <description>IPv4 address for dynamic authorization server</description> </valueHelp> </properties> </leafNode> diff --git a/interface-definitions/include/haproxy/tcp-request.xml.i b/interface-definitions/include/haproxy/tcp-request.xml.i new file mode 100644 index 000000000..3d60bd8ad --- /dev/null +++ b/interface-definitions/include/haproxy/tcp-request.xml.i @@ -0,0 +1,22 @@ +<!-- include start from haproxy/tcp-request.xml.i --> +<node name="tcp-request"> + <properties> + <help>TCP request directive</help> + </properties> + <children> + <leafNode name="inspect-delay"> + <properties> + <help>Set the maximum allowed time to wait for data during content inspection</help> + <valueHelp> + <format>u32:1-65535</format> + <description>The timeout value specified in milliseconds</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-65535"/> + </constraint> + <constraintErrorMessage>The timeout value must be in range 1 to 65535 milliseconds</constraintErrorMessage> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/load-balancing_reverse-proxy.xml.in b/interface-definitions/load-balancing_reverse-proxy.xml.in index eb01580da..6a3b3cef1 100644 --- a/interface-definitions/load-balancing_reverse-proxy.xml.in +++ b/interface-definitions/load-balancing_reverse-proxy.xml.in @@ -38,6 +38,7 @@ #include <include/haproxy/mode.xml.i> #include <include/port-number.xml.i> #include <include/haproxy/rule-frontend.xml.i> + #include <include/haproxy/tcp-request.xml.i> <leafNode name="redirect-http-to-https"> <properties> <help>Redirect HTTP to HTTPS</help> diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index 833019d68..7f425d982 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -768,6 +768,26 @@ <children> #include <include/ipsec/authentication-id.xml.i> #include <include/ipsec/authentication-x509.xml.i> + <leafNode name="eap-id"> + <properties> + <help>Remote EAP ID for client authentication</help> + <valueHelp> + <format>txt</format> + <description>Remote EAP ID for client authentication</description> + </valueHelp> + <completionHelp> + <list>any</list> + </completionHelp> + <valueHelp> + <format>any</format> + <description>Allow any EAP ID</description> + </valueHelp> + <constraint> + <regex>[[:ascii:]]{1,64}</regex> + </constraint> + </properties> + <defaultValue>any</defaultValue> + </leafNode> <leafNode name="client-mode"> <properties> <help>Client authentication mode</help> diff --git a/python/vyos/utils/convert.py b/python/vyos/utils/convert.py index c02f0071e..41e65081f 100644 --- a/python/vyos/utils/convert.py +++ b/python/vyos/utils/convert.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 @@ -19,38 +19,43 @@ def seconds_to_human(s, separator=""): """ s = int(s) + year = 60 * 60 * 24 * 365.25 week = 60 * 60 * 24 * 7 day = 60 * 60 * 24 hour = 60 * 60 - remainder = 0 - result = "" + result = [] + + years = s // year + if years > 0: + result.append(f'{int(years)}y') + s = int(s % year) weeks = s // week if weeks > 0: - result = "{0}w".format(weeks) + result.append(f'{weeks}w') s = s % week days = s // day if days > 0: - result = "{0}{1}{2}d".format(result, separator, days) + result.append(f'{days}d') s = s % day hours = s // hour if hours > 0: - result = "{0}{1}{2}h".format(result, separator, hours) + result.append(f'{hours}h') s = s % hour minutes = s // 60 if minutes > 0: - result = "{0}{1}{2}m".format(result, separator, minutes) + result.append(f'{minutes}m') s = s % 60 seconds = s if seconds > 0: - result = "{0}{1}{2}s".format(result, separator, seconds) + result.append(f'{seconds}s') - return result + return separator.join(result) def bytes_to_human(bytes, initial_exponent=0, precision=2, int_below_exponent=0): diff --git a/smoketest/scripts/cli/test_load-balancing_reverse-proxy.py b/smoketest/scripts/cli/test_load-balancing_reverse-proxy.py index 737c07401..f9f163782 100755 --- a/smoketest/scripts/cli/test_load-balancing_reverse-proxy.py +++ b/smoketest/scripts/cli/test_load-balancing_reverse-proxy.py @@ -299,39 +299,86 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase): self.cli_commit() def test_05_lb_reverse_proxy_backend_http_check(self): - # Setup base - self.base_config() - - # Set http-check - self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'method', 'get']) - self.cli_commit() - - # Test http-check - config = read_file(HAPROXY_CONF) - self.assertIn('option httpchk', config) - self.assertIn('http-check send meth GET', config) - - # Set http-check with uri and status - self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'uri', '/health']) - self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'expect', 'status', '200']) - self.cli_commit() - - # Test http-check with uri and status - config = read_file(HAPROXY_CONF) - self.assertIn('option httpchk', config) - self.assertIn('http-check send meth GET uri /health', config) - self.assertIn('http-check expect status 200', config) - - # Set http-check with string - self.cli_delete(base_path + ['backend', 'bk-01', 'http-check', 'expect', 'status', '200']) - self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'expect', 'string', 'success']) - self.cli_commit() - - # Test http-check with string - config = read_file(HAPROXY_CONF) - self.assertIn('option httpchk', config) - self.assertIn('http-check send meth GET uri /health', config) - self.assertIn('http-check expect string success', config) + # Setup base + self.base_config() + + # Set http-check + self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'method', 'get']) + self.cli_commit() + + # Test http-check + config = read_file(HAPROXY_CONF) + self.assertIn('option httpchk', config) + self.assertIn('http-check send meth GET', config) + + # Set http-check with uri and status + self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'uri', '/health']) + self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'expect', 'status', '200']) + self.cli_commit() + + # Test http-check with uri and status + config = read_file(HAPROXY_CONF) + self.assertIn('option httpchk', config) + self.assertIn('http-check send meth GET uri /health', config) + self.assertIn('http-check expect status 200', config) + + # Set http-check with string + self.cli_delete(base_path + ['backend', 'bk-01', 'http-check', 'expect', 'status', '200']) + self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'expect', 'string', 'success']) + self.cli_commit() + + # Test http-check with string + config = read_file(HAPROXY_CONF) + self.assertIn('option httpchk', config) + self.assertIn('http-check send meth GET uri /health', config) + self.assertIn('http-check expect string success', config) + + def test_06_lb_reverse_proxy_tcp_mode(self): + frontend = 'tcp_8443' + mode = 'tcp' + front_port = '8433' + tcp_request_delay = "5000" + rule_thirty = '30' + domain_bk = 'n6.example.com' + ssl_opt = "req-ssl-sni" + bk_name = 'bk-03' + bk_server = '192.0.2.11' + bk_server_port = '9090' + + back_base = base_path + ['backend'] + + self.cli_set(base_path + ['service', frontend, 'mode', mode]) + self.cli_set(base_path + ['service', frontend, 'port', front_port]) + self.cli_set(base_path + ['service', frontend, 'tcp-request', 'inspect-delay', tcp_request_delay]) + + self.cli_set(base_path + ['service', frontend, 'rule', rule_thirty, 'domain-name', domain_bk]) + self.cli_set(base_path + ['service', frontend, 'rule', rule_thirty, 'ssl', ssl_opt]) + self.cli_set(base_path + ['service', frontend, 'rule', rule_thirty, 'set', 'backend', bk_name]) + + self.cli_set(back_base + [bk_name, 'mode', mode]) + self.cli_set(back_base + [bk_name, 'server', bk_name, 'address', bk_server]) + self.cli_set(back_base + [bk_name, 'server', bk_name, 'port', bk_server_port]) + + # commit changes + self.cli_commit() + + config = read_file(HAPROXY_CONF) + + # Frontend + self.assertIn(f'frontend {frontend}', config) + self.assertIn(f'bind :::{front_port} v4v6', config) + self.assertIn(f'mode {mode}', config) + + self.assertIn(f'tcp-request inspect-delay {tcp_request_delay}', config) + self.assertIn(f"tcp-request content accept if {{ req_ssl_hello_type 1 }}", config) + self.assertIn(f'acl {rule_thirty} req_ssl_sni -i {domain_bk}', config) + self.assertIn(f'use_backend {bk_name} if {rule_thirty}', config) + + # Backend + self.assertIn(f'backend {bk_name}', config) + self.assertIn(f'balance roundrobin', config) + self.assertIn(f'mode {mode}', config) + self.assertIn(f'server {bk_name} {bk_server}:{bk_server_port}', config) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py index 145b5990e..27356d70e 100755 --- a/smoketest/scripts/cli/test_vpn_ipsec.py +++ b/smoketest/scripts/cli/test_vpn_ipsec.py @@ -782,6 +782,11 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase): self.assertTrue(os.path.exists(os.path.join(CA_PATH, f'{ca_name}.pem'))) self.assertTrue(os.path.exists(os.path.join(CERT_PATH, f'{peer_name}.pem'))) + # Test setting of custom EAP ID + self.cli_set(base_path + ['remote-access', 'connection', conn_name, 'authentication', 'eap-id', 'eap-user@vyos.net']) + self.cli_commit() + self.assertIn(r'eap_id = eap-user@vyos.net', read_file(swanctl_file)) + self.tearDownPKI() def test_remote_access_x509(self): diff --git a/src/etc/rsyslog.conf b/src/etc/rsyslog.conf index 9781f0835..b3f41acb6 100644 --- a/src/etc/rsyslog.conf +++ b/src/etc/rsyslog.conf @@ -15,21 +15,6 @@ $KLogPath /proc/kmsg #### GLOBAL DIRECTIVES #### ########################### -# The lines below cause all listed daemons/processes to be logged into -# /var/log/auth.log, then drops the message so it does not also go to the -# regular syslog so that messages are not duplicated - -$outchannel auth_log,/var/log/auth.log -if $programname == 'CRON' or - $programname == 'sudo' or - $programname == 'su' - then :omfile:$auth_log - -if $programname == 'CRON' or - $programname == 'sudo' or - $programname == 'su' - then stop - # Use traditional timestamp format. # To enable high precision timestamps, comment out the following line. # A modern-style logfile format similar to TraditionalFileFormat, buth with high-precision timestamps and timezone information @@ -60,6 +45,21 @@ $Umask 0022 # $IncludeConfig /etc/rsyslog.d/*.conf +# The lines below cause all listed daemons/processes to be logged into +# /var/log/auth.log, then drops the message so it does not also go to the +# regular syslog so that messages are not duplicated + +$outchannel auth_log,/var/log/auth.log +if $programname == 'CRON' or + $programname == 'sudo' or + $programname == 'su' + then :omfile:$auth_log + +if $programname == 'CRON' or + $programname == 'sudo' or + $programname == 'su' + then stop + ############### #### RULES #### ############### diff --git a/src/helpers/vyos-vrrp-conntracksync.sh b/src/helpers/vyos-vrrp-conntracksync.sh index 0cc718938..90fa77f23 100755 --- a/src/helpers/vyos-vrrp-conntracksync.sh +++ b/src/helpers/vyos-vrrp-conntracksync.sh @@ -25,7 +25,7 @@ LOGCMD="logger -t $TAG -p $FACILITY.$LEVEL" VRRP_GRP="VRRP sync-group [$2]" FAILOVER_STATE="/var/run/vyatta-conntrackd-failover-state" -$LOGCMD "vyatta-vrrp-conntracksync invoked at `date`" +$LOGCMD "vyos-vrrp-conntracksync invoked at `date`" if ! systemctl is-active --quiet conntrackd.service; then echo "conntrackd service not running" @@ -148,7 +148,7 @@ case "$1" in *) echo UNKNOWN at `date` > $FAILOVER_STATE $LOGCMD "ERROR: `uname -n` unknown state transition for $VRRP_GRP" - echo "Usage: vyatta-vrrp-conntracksync.sh {master|backup|fault}" + echo "Usage: vyos-vrrp-conntracksync.sh {master|backup|fault}" exit 1 ;; esac diff --git a/src/op_mode/connect_disconnect.py b/src/op_mode/connect_disconnect.py index bd02dc6ea..373f9e953 100755 --- a/src/op_mode/connect_disconnect.py +++ b/src/op_mode/connect_disconnect.py @@ -48,7 +48,7 @@ def connect(interface): if os.path.isdir(f'/sys/class/net/{interface}'): print(f'Interface {interface}: already connected!') elif check_ppp_running(interface): - print(f'Interface {interface}: connection is beeing established!') + print(f'Interface {interface}: connection is being established!') else: print(f'Interface {interface}: connecting...') call(f'systemctl restart ppp@{interface}.service') @@ -58,7 +58,7 @@ def connect(interface): else: call(f'VYOS_TAGNODE_VALUE={interface} /usr/libexec/vyos/conf_mode/interfaces_wwan.py') else: - print(f'Unknown interface {interface}, can not connect. Aborting!') + print(f'Unknown interface {interface}, cannot connect. Aborting!') # Reaply QoS configuration config = ConfigTreeQuery() @@ -90,7 +90,7 @@ def disconnect(interface): modem = interface.lstrip('wwan') call(f'mmcli --modem {modem} --simple-disconnect', stdout=DEVNULL) else: - print(f'Unknown interface {interface}, can not disconnect. Aborting!') + print(f'Unknown interface {interface}, cannot disconnect. Aborting!') def main(): parser = argparse.ArgumentParser() diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py index b1311b6f9..ba0e3b6db 100755 --- a/src/op_mode/image_installer.py +++ b/src/op_mode/image_installer.py @@ -26,6 +26,7 @@ from os import environ from typing import Union from urllib.parse import urlparse from passlib.hosts import linux_context +from errno import ENOSPC from psutil import disk_partitions @@ -939,6 +940,16 @@ def add_image(image_path: str, vrf: str = None, username: str = '', if set_as_default: grub.set_default(image_name, root_dir) + except OSError as e: + # if no space error, remove image dir and cleanup + if e.errno == ENOSPC: + cleanup(mounts=[str(iso_path)], + remove_items=[f'{root_dir}/boot/{image_name}']) + else: + # unmount an ISO and cleanup + cleanup([str(iso_path)]) + exit(f'Error: {e}') + except Exception as err: # unmount an ISO and cleanup cleanup([str(iso_path)]) diff --git a/src/op_mode/uptime.py b/src/op_mode/uptime.py index d6adf6f4d..059a4c3f6 100755 --- a/src/op_mode/uptime.py +++ b/src/op_mode/uptime.py @@ -49,7 +49,7 @@ def _get_raw_data(): res = {} res["uptime_seconds"] = _get_uptime_seconds() - res["uptime"] = seconds_to_human(_get_uptime_seconds()) + res["uptime"] = seconds_to_human(_get_uptime_seconds(), separator=' ') res["load_average"] = _get_load_averages() return res |