summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/frr/isisd.frr.j214
-rw-r--r--data/templates/frr/ospfd.frr.j27
-rw-r--r--data/templates/login/pam_otp_ga.conf.j27
-rw-r--r--data/templates/ssh/sshd_config.j24
-rw-r--r--data/templates/telegraf/telegraf.j22
-rw-r--r--debian/vyos-1x.postinst8
-rw-r--r--interface-definitions/include/isis/protocol-common-config.xml.i4
-rw-r--r--interface-definitions/include/monitoring/url.xml.i15
-rw-r--r--interface-definitions/include/ospf/protocol-common-config.xml.i4
-rw-r--r--interface-definitions/include/segment-routing-label-value.xml.i (renamed from interface-definitions/include/isis/high-low-label-value.xml.i)4
-rw-r--r--interface-definitions/service-monitoring-telegraf.xml.in6
-rw-r--r--interface-definitions/system-login.xml.in64
-rw-r--r--python/vyos/defaults.py2
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_isis.py8
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_ospf.py13
-rwxr-xr-xsmoketest/scripts/cli/test_service_monitoring_telegraf.py1
-rwxr-xr-xsmoketest/scripts/cli/test_system_login.py24
-rwxr-xr-xsrc/conf_mode/http-api.py63
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py5
-rwxr-xr-xsrc/conf_mode/service_monitoring_telegraf.py6
-rwxr-xr-xsrc/conf_mode/system-login.py9
-rw-r--r--src/etc/sudoers.d/vyos5
-rwxr-xr-xsrc/etc/telegraf/custom_scripts/show_firewall_input_filter.py5
-rwxr-xr-xsrc/op_mode/ipsec.py5
-rwxr-xr-xsrc/services/vyos-http-api-server12
25 files changed, 198 insertions, 99 deletions
diff --git a/data/templates/frr/isisd.frr.j2 b/data/templates/frr/isisd.frr.j2
index 194dbcb07..8df1e9513 100644
--- a/data/templates/frr/isisd.frr.j2
+++ b/data/templates/frr/isisd.frr.j2
@@ -121,22 +121,12 @@ router isis VyOS {{ 'vrf ' + vrf if vrf is vyos_defined }}
{% for prefix, prefix_config in segment_routing.prefix.items() %}
{% if prefix_config.absolute is vyos_defined %}
{% if prefix_config.absolute.value is vyos_defined %}
- segment-routing prefix {{ prefix }} absolute {{ prefix_config.absolute.value }}
-{% if prefix_config.absolute.explicit_null is vyos_defined %}
- segment-routing prefix {{ prefix }} absolute {{ prefix_config.absolute.value }} explicit-null
-{% elif prefix_config.absolute.no_php_flag is vyos_defined %}
- segment-routing prefix {{ prefix }} absolute {{ prefix_config.absolute.value }} no-php-flag
-{% endif %}
+ segment-routing prefix {{ prefix }} absolute {{ prefix_config.absolute.value }} {{ 'explicit-null' if prefix_config.absolute.explicit_null is vyos_defined }} {{ 'no-php-flag' if prefix_config.absolute.no_php_flag is vyos_defined }}
{% endif %}
{% endif %}
{% if prefix_config.index is vyos_defined %}
{% if prefix_config.index.value is vyos_defined %}
- segment-routing prefix {{ prefix }} index {{ prefix_config.index.value }}
-{% if prefix_config.index.explicit_null is vyos_defined %}
- segment-routing prefix {{ prefix }} index {{ prefix_config.index.value }} explicit-null
-{% elif prefix_config.index.no_php_flag is vyos_defined %}
- segment-routing prefix {{ prefix }} index {{ prefix_config.index.value }} no-php-flag
-{% endif %}
+ segment-routing prefix {{ prefix }} index {{ prefix_config.index.value }} {{ 'explicit-null' if prefix_config.index.explicit_null is vyos_defined }} {{ 'no-php-flag' if prefix_config.index.no_php_flag is vyos_defined }}
{% endif %}
{% endif %}
{% endfor %}
diff --git a/data/templates/frr/ospfd.frr.j2 b/data/templates/frr/ospfd.frr.j2
index 9cd9b03dc..2a8afefbc 100644
--- a/data/templates/frr/ospfd.frr.j2
+++ b/data/templates/frr/ospfd.frr.j2
@@ -196,12 +196,7 @@ router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% for prefix, prefix_config in segment_routing.prefix.items() %}
{% if prefix_config.index is vyos_defined %}
{% if prefix_config.index.value is vyos_defined %}
- segment-routing prefix {{ prefix }} index {{ prefix_config.index.value }}
-{% if prefix_config.index.explicit_null is vyos_defined %}
- segment-routing prefix {{ prefix }} index {{ prefix_config.index.value }} explicit-null
-{% elif prefix_config.index.no_php_flag is vyos_defined %}
- segment-routing prefix {{ prefix }} index {{ prefix_config.index.value }} no-php-flag
-{% endif %}
+ segment-routing prefix {{ prefix }} index {{ prefix_config.index.value }} {{ 'explicit-null' if prefix_config.index.explicit_null is vyos_defined }} {{ 'no-php-flag' if prefix_config.index.no_php_flag is vyos_defined }}
{% endif %}
{% endif %}
{% endfor %}
diff --git a/data/templates/login/pam_otp_ga.conf.j2 b/data/templates/login/pam_otp_ga.conf.j2
new file mode 100644
index 000000000..cf51ce089
--- /dev/null
+++ b/data/templates/login/pam_otp_ga.conf.j2
@@ -0,0 +1,7 @@
+{% if authentication.otp.key is vyos_defined %}
+{{ authentication.otp.key | upper }}
+" RATE_LIMIT {{ authentication.otp.rate_limit }} {{ authentication.otp.rate_time }}
+" WINDOW_SIZE {{ authentication.otp.window_size }}
+" DISALLOW_REUSE
+" TOTP_AUTH
+{% endif %}
diff --git a/data/templates/ssh/sshd_config.j2 b/data/templates/ssh/sshd_config.j2
index 79b07478b..5bbfdeb88 100644
--- a/data/templates/ssh/sshd_config.j2
+++ b/data/templates/ssh/sshd_config.j2
@@ -17,7 +17,6 @@ PubkeyAuthentication yes
IgnoreRhosts yes
HostbasedAuthentication no
PermitEmptyPasswords no
-ChallengeResponseAuthentication no
X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
@@ -30,6 +29,7 @@ PermitRootLogin no
PidFile /run/sshd/sshd.pid
AddressFamily any
DebianBanner no
+PasswordAuthentication no
#
# User configurable section
@@ -48,7 +48,7 @@ Port {{ value }}
LogLevel {{ loglevel | upper }}
# Specifies whether password authentication is allowed
-PasswordAuthentication {{ "no" if disable_password_authentication is vyos_defined else "yes" }}
+ChallengeResponseAuthentication {{ "no" if disable_password_authentication is vyos_defined else "yes" }}
{% if listen_address is vyos_defined %}
# Specifies the local addresses sshd should listen on
diff --git a/data/templates/telegraf/telegraf.j2 b/data/templates/telegraf/telegraf.j2
index 2d14230ae..36571ce98 100644
--- a/data/templates/telegraf/telegraf.j2
+++ b/data/templates/telegraf/telegraf.j2
@@ -110,7 +110,7 @@
server = "unixgram:///run/telegraf/telegraf_syslog.sock"
best_effort = true
syslog_standard = "RFC3164"
-{% if influxdb_configured is vyos_defined %}
+{% if influxdb is vyos_defined %}
[[inputs.exec]]
commands = [
"{{ custom_scripts_dir }}/show_firewall_input_filter.py",
diff --git a/debian/vyos-1x.postinst b/debian/vyos-1x.postinst
index 6879b6e4f..031e91595 100644
--- a/debian/vyos-1x.postinst
+++ b/debian/vyos-1x.postinst
@@ -21,6 +21,14 @@ if ! grep -q '^openvpn' /etc/passwd; then
adduser --quiet --firstuid 100 --system --group --shell /usr/sbin/nologin openvpn
fi
+# Add 2FA support for SSH
+sudo grep -qF -- "auth required pam_google_authenticator.so nullok" "/etc/pam.d/sshd" || \
+sudo sed -i '/^@include common-auth/a # Check OTP 2FA, if configured for the user\nauth required pam_google_authenticator.so nullok' /etc/pam.d/sshd
+
+# Add 2FA support for local authentication
+sudo grep -qF -- "auth required pam_google_authenticator.so nullok" "/etc/pam.d/login" || \
+sudo sed -i '/^@include common-auth/a # Check OTP 2FA, if configured for the user\nauth required pam_google_authenticator.so nullok' /etc/pam.d/login
+
# Add RADIUS operator user for RADIUS authenticated users to map to
if ! grep -q '^radius_user' /etc/passwd; then
adduser --quiet --firstuid 1000 --disabled-login --ingroup vyattaop \
diff --git a/interface-definitions/include/isis/protocol-common-config.xml.i b/interface-definitions/include/isis/protocol-common-config.xml.i
index 57ee19300..42bda7a80 100644
--- a/interface-definitions/include/isis/protocol-common-config.xml.i
+++ b/interface-definitions/include/isis/protocol-common-config.xml.i
@@ -238,7 +238,7 @@
<help>Segment Routing Global Block label range</help>
</properties>
<children>
- #include <include/isis/high-low-label-value.xml.i>
+ #include <include/segment-routing-label-value.xml.i>
</children>
</node>
<node name="local-block">
@@ -246,7 +246,7 @@
<help>Segment Routing Local Block label range</help>
</properties>
<children>
- #include <include/isis/high-low-label-value.xml.i>
+ #include <include/segment-routing-label-value.xml.i>
</children>
</node>
<leafNode name="maximum-label-depth">
diff --git a/interface-definitions/include/monitoring/url.xml.i b/interface-definitions/include/monitoring/url.xml.i
deleted file mode 100644
index fd61c38ea..000000000
--- a/interface-definitions/include/monitoring/url.xml.i
+++ /dev/null
@@ -1,15 +0,0 @@
-<!-- include start from monitoring/url.xml.i -->
-<leafNode name="url">
- <properties>
- <help>Remote URL</help>
- <valueHelp>
- <format>url</format>
- <description>Remote URL</description>
- </valueHelp>
- <constraint>
- <regex>(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}?(\/.*)?</regex>
- </constraint>
- <constraintErrorMessage>Incorrect URL format</constraintErrorMessage>
- </properties>
-</leafNode>
-<!-- include end -->
diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i
index 28e3b473b..0615063af 100644
--- a/interface-definitions/include/ospf/protocol-common-config.xml.i
+++ b/interface-definitions/include/ospf/protocol-common-config.xml.i
@@ -631,7 +631,7 @@
<help>Segment Routing Global Block label range</help>
</properties>
<children>
- #include <include/isis/high-low-label-value.xml.i>
+ #include <include/segment-routing-label-value.xml.i>
</children>
</node>
<node name="local-block">
@@ -639,7 +639,7 @@
<help>Segment Routing Local Block label range</help>
</properties>
<children>
- #include <include/isis/high-low-label-value.xml.i>
+ #include <include/segment-routing-label-value.xml.i>
</children>
</node>
<leafNode name="maximum-label-depth">
diff --git a/interface-definitions/include/isis/high-low-label-value.xml.i b/interface-definitions/include/segment-routing-label-value.xml.i
index f30b5af3a..05e1edd78 100644
--- a/interface-definitions/include/isis/high-low-label-value.xml.i
+++ b/interface-definitions/include/segment-routing-label-value.xml.i
@@ -1,10 +1,10 @@
-<!-- include start from isis/high-low-label-value.xml.i -->
+<!-- include start from segment-routing-label-value.xml.i -->
<leafNode name="low-label-value">
<properties>
<help>MPLS label lower bound</help>
<valueHelp>
<format>u32:16-1048575</format>
- <description>Label value (recommended minimum value: 100)</description>
+ <description>Label value (recommended minimum value: 300)</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 16-1048575"/>
diff --git a/interface-definitions/service-monitoring-telegraf.xml.in b/interface-definitions/service-monitoring-telegraf.xml.in
index 47f943d83..f50e5e334 100644
--- a/interface-definitions/service-monitoring-telegraf.xml.in
+++ b/interface-definitions/service-monitoring-telegraf.xml.in
@@ -53,7 +53,7 @@
</properties>
<defaultValue>main</defaultValue>
</leafNode>
- #include <include/monitoring/url.xml.i>
+ #include <include/url.xml.i>
#include <include/port-number.xml.i>
<leafNode name="port">
<defaultValue>8086</defaultValue>
@@ -145,7 +145,7 @@
<constraintErrorMessage>Table is limited to alphanumerical characters and can contain hyphen and underscores</constraintErrorMessage>
</properties>
</leafNode>
- #include <include/monitoring/url.xml.i>
+ #include <include/url.xml.i>
</children>
</node>
<leafNode name="source">
@@ -271,7 +271,7 @@
</leafNode>
</children>
</node>
- #include <include/monitoring/url.xml.i>
+ #include <include/url.xml.i>
</children>
</node>
#include <include/interface/vrf.xml.i>
diff --git a/interface-definitions/system-login.xml.in b/interface-definitions/system-login.xml.in
index d189be3f8..def42544a 100644
--- a/interface-definitions/system-login.xml.in
+++ b/interface-definitions/system-login.xml.in
@@ -19,7 +19,7 @@
<children>
<node name="authentication">
<properties>
- <help>Password authentication</help>
+ <help>Authentication settings</help>
</properties>
<children>
<leafNode name="encrypted-password">
@@ -36,6 +36,68 @@
</properties>
<defaultValue>!</defaultValue>
</leafNode>
+ <node name="otp">
+ <properties>
+ <help>One-Time-Pad (two-factor) authentication parameters</help>
+ </properties>
+ <children>
+ <leafNode name="rate-limit">
+ <properties>
+ <help>Limit number of logins (rate-limit) per rate-time</help>
+ <valueHelp>
+ <format>u32:1-10</format>
+ <description>Number of attempts</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-10"/>
+ </constraint>
+ <constraintErrorMessage>Number of login attempts must me between 1 and 10</constraintErrorMessage>
+ </properties>
+ <defaultValue>3</defaultValue>
+ </leafNode>
+ <leafNode name="rate-time">
+ <properties>
+ <help>Limit number of logins (rate-limit) per rate-time</help>
+ <valueHelp>
+ <format>u32:15-600</format>
+ <description>Time interval</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 15-600"/>
+ </constraint>
+ <constraintErrorMessage>Rate limit time interval must be between 15 and 600 seconds</constraintErrorMessage>
+ </properties>
+ <defaultValue>30</defaultValue>
+ </leafNode>
+ <leafNode name="window-size">
+ <properties>
+ <help>Set window of concurrently valid codes</help>
+ <valueHelp>
+ <format>u32:1-21</format>
+ <description>Window size</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-21"/>
+ </constraint>
+ <constraintErrorMessage>Window of concurrently valid codes must be between 1 and 21</constraintErrorMessage>
+ </properties>
+ <defaultValue>3</defaultValue>
+ </leafNode>
+ <leafNode name="key">
+ <properties>
+ <help>Key/secret the token algorithm (see RFC4226)</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Base32 encoded key/token</description>
+ </valueHelp>
+ <constraint>
+ <regex>[a-zA-Z2-7]{26,10000}</regex>
+ </constraint>
+ <constraintErrorMessage>Key must only include base32 characters and be at least 26 characters long</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
<leafNode name="plaintext-password">
<properties>
<help>Plaintext password used for encryption</help>
diff --git a/python/vyos/defaults.py b/python/vyos/defaults.py
index 6894fc4da..7de458960 100644
--- a/python/vyos/defaults.py
+++ b/python/vyos/defaults.py
@@ -49,8 +49,6 @@ api_data = {
'port' : '8080',
'socket' : False,
'strict' : False,
- 'gql' : False,
- 'introspection' : False,
'debug' : False,
'api_keys' : [ {"id": "testapp", "key": "qwerty"} ]
}
diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py
index c26028253..d11d80a1f 100755
--- a/smoketest/scripts/cli/test_protocols_isis.py
+++ b/smoketest/scripts/cli/test_protocols_isis.py
@@ -263,10 +263,10 @@ class TestProtocolsISIS(VyOSUnitTestSHIM.TestCase):
self.assertIn(f' isis bfd profile {bfd_profile}', tmp)
def test_isis_07_segment_routing_configuration(self):
- global_block_low = "100"
- global_block_high = "199"
- local_block_low = "200"
- local_block_high = "299"
+ global_block_low = "300"
+ global_block_high = "399"
+ local_block_low = "400"
+ local_block_high = "499"
interface = 'lo'
maximum_stack_size = '5'
prefix_one = '192.168.0.1/32'
diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py
index 93bb761c1..51c947537 100755
--- a/smoketest/scripts/cli/test_protocols_ospf.py
+++ b/smoketest/scripts/cli/test_protocols_ospf.py
@@ -382,10 +382,10 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):
def test_ospf_14_segment_routing_configuration(self):
- global_block_low = "100"
- global_block_high = "199"
- local_block_low = "200"
- local_block_high = "299"
+ global_block_low = "300"
+ global_block_high = "399"
+ local_block_low = "400"
+ local_block_high = "499"
interface = 'lo'
maximum_stack_size = '5'
prefix_one = '192.168.0.1/32'
@@ -408,16 +408,13 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):
self.cli_commit()
# Verify all changes
-
frrconfig = self.getFRRconfig('router ospf')
+ self.assertIn(f' segment-routing on', frrconfig)
self.assertIn(f' segment-routing global-block {global_block_low} {global_block_high} local-block {local_block_low} {local_block_high}', frrconfig)
self.assertIn(f' segment-routing node-msd {maximum_stack_size}', frrconfig)
self.assertIn(f' segment-routing prefix {prefix_one} index {prefix_one_value} explicit-null', frrconfig)
self.assertIn(f' segment-routing prefix {prefix_two} index {prefix_two_value} no-php-flag', frrconfig)
- self.skipTest('https://github.com/FRRouting/frr/issues/12007')
- self.assertIn(f' segment-routing on', frrconfig)
-
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_service_monitoring_telegraf.py b/smoketest/scripts/cli/test_service_monitoring_telegraf.py
index c1c4044e6..ed486c3b9 100755
--- a/smoketest/scripts/cli/test_service_monitoring_telegraf.py
+++ b/smoketest/scripts/cli/test_service_monitoring_telegraf.py
@@ -60,6 +60,7 @@ class TestMonitoringTelegraf(VyOSUnitTestSHIM.TestCase):
self.assertIn(f' token = "$INFLUX_TOKEN"', config)
self.assertIn(f'urls = ["{url}:{port}"]', config)
self.assertIn(f'bucket = "{bucket}"', config)
+ self.assertIn(f'[[inputs.exec]]', config)
for input in inputs:
self.assertIn(input, config)
diff --git a/smoketest/scripts/cli/test_system_login.py b/smoketest/scripts/cli/test_system_login.py
index 1131b6f93..6006fe0f6 100755
--- a/smoketest/scripts/cli/test_system_login.py
+++ b/smoketest/scripts/cli/test_system_login.py
@@ -46,6 +46,14 @@ TTSb0X1zPGxPIRFy5GoGtO9Mm5h4OZk=
"""
class TestSystemLogin(VyOSUnitTestSHIM.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super(TestSystemLogin, cls).setUpClass()
+
+ # ensure we can also run this test on a live system - so lets clean
+ # out the current configuration which will break this test
+ cls.cli_delete(cls, base_path + ['radius'])
+
def tearDown(self):
# Delete individual users from configuration
for user in users:
@@ -97,6 +105,22 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase):
# b'Linux LR1.wue3 5.10.61-amd64-vyos #1 SMP Fri Aug 27 08:55:46 UTC 2021 x86_64 GNU/Linux\n'
self.assertTrue(len(stdout) > 40)
+ def test_system_login_otp(self):
+ otp_user = 'otp-test_user'
+ otp_password = 'SuperTestPassword'
+ otp_key = '76A3ZS6HFHBTOK2H4NDHTIVFPQ'
+
+ self.cli_set(base_path + ['user', otp_user, 'authentication', 'plaintext-password', otp_password])
+ self.cli_set(base_path + ['user', otp_user, 'authentication', 'otp', 'key', otp_key])
+
+ self.cli_commit()
+
+ # Check if OTP key was written properly
+ tmp = cmd(f'sudo head -1 /home/{otp_user}/.google_authenticator')
+ self.assertIn(otp_key, tmp)
+
+ self.cli_delete(base_path + ['user', otp_user])
+
def test_system_user_ssh_key(self):
ssh_user = 'ssh-test_user'
public_keys = 'vyos_test@domain-foo.com'
diff --git a/src/conf_mode/http-api.py b/src/conf_mode/http-api.py
index 04113fc09..c196e272b 100755
--- a/src/conf_mode/http-api.py
+++ b/src/conf_mode/http-api.py
@@ -24,9 +24,11 @@ from copy import deepcopy
import vyos.defaults
from vyos.config import Config
+from vyos.configdict import dict_merge
from vyos.template import render
from vyos.util import cmd
from vyos.util import call
+from vyos.xml import defaults
from vyos import ConfigError
from vyos import airbag
airbag.enable()
@@ -36,6 +38,15 @@ systemd_service = '/run/systemd/system/vyos-http-api.service'
vyos_conf_scripts_dir=vyos.defaults.directories['conf_mode']
+def _translate_values_to_boolean(d: dict) -> dict:
+ for k in list(d):
+ if d[k] == {}:
+ d[k] = True
+ elif isinstance(d[k], dict):
+ _translate_values_to_boolean(d[k])
+ else:
+ pass
+
def get_config(config=None):
http_api = deepcopy(vyos.defaults.api_data)
x = http_api.get('api_keys')
@@ -54,48 +65,40 @@ def get_config(config=None):
if not conf.exists(base):
return None
+ api_dict = conf.get_config_dict(base, key_mangling=('-', '_'),
+ no_tag_node_value_mangle=True,
+ get_first_key=True)
+
+ # One needs to 'flatten' the keys dict from the config into the
+ # http-api.conf format for api_keys:
+ if 'keys' in api_dict:
+ api_dict['api_keys'] = []
+ for el in list(api_dict['keys']['id']):
+ key = api_dict['keys']['id'][el]['key']
+ api_dict['api_keys'].append({'id': el, 'key': key})
+ del api_dict['keys']
+
# Do we run inside a VRF context?
vrf_path = ['service', 'https', 'vrf']
if conf.exists(vrf_path):
http_api['vrf'] = conf.return_value(vrf_path)
- conf.set_level('service https api')
- if conf.exists('strict'):
- http_api['strict'] = True
-
- if conf.exists('debug'):
- http_api['debug'] = True
+ if 'api_keys' in api_dict:
+ keys_added = True
- if conf.exists('gql'):
- http_api['gql'] = True
- if conf.exists('gql introspection'):
- http_api['introspection'] = True
+ if 'gql' in api_dict:
+ api_dict = dict_merge(defaults(base), api_dict)
- if conf.exists('socket'):
- http_api['socket'] = True
-
- if conf.exists('port'):
- port = conf.return_value('port')
- http_api['port'] = port
-
- if conf.exists('cors'):
- http_api['cors'] = {}
- if conf.exists('cors allow-origin'):
- origins = conf.return_values('cors allow-origin')
- http_api['cors']['origins'] = origins[:]
-
- if conf.exists('keys'):
- for name in conf.list_nodes('keys id'):
- if conf.exists('keys id {0} key'.format(name)):
- key = conf.return_value('keys id {0} key'.format(name))
- new_key = { 'id': name, 'key': key }
- http_api['api_keys'].append(new_key)
- keys_added = True
+ http_api.update(api_dict)
if keys_added and default_key:
if default_key in http_api['api_keys']:
http_api['api_keys'].remove(default_key)
+ # Finally, translate entries in http_api into boolean settings for
+ # backwards compatability of JSON http-api.conf file
+ _translate_values_to_boolean(http_api)
+
return http_api
def verify(http_api):
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index 87456f00b..ff568d470 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -159,6 +159,11 @@ def verify(bgp):
if 'ebgp_multihop' in peer_config and 'ttl_security' in peer_config:
raise ConfigError('You can not set both ebgp-multihop and ttl-security hops')
+ # interface and ebgp-multihop can't be used in the same configration
+ if 'ebgp_multihop' in peer_config and 'interface' in peer_config:
+ raise ConfigError(f'Ebgp-multihop can not be used with directly connected '\
+ f'neighbor "{peer}"')
+
# Check if neighbor has both override capability and strict capability match
# configured at the same time.
if 'override_capability' in peer_config and 'strict_capability_match' in peer_config:
diff --git a/src/conf_mode/service_monitoring_telegraf.py b/src/conf_mode/service_monitoring_telegraf.py
index 427cb6911..aafece47a 100755
--- a/src/conf_mode/service_monitoring_telegraf.py
+++ b/src/conf_mode/service_monitoring_telegraf.py
@@ -42,7 +42,11 @@ systemd_override = '/etc/systemd/system/telegraf.service.d/10-override.conf'
def get_nft_filter_chains():
""" Get nft chains for table filter """
- nft = cmd('nft --json list table ip vyos_filter')
+ try:
+ nft = cmd('nft --json list table ip vyos_filter')
+ except Exception:
+ print('nft table ip vyos_filter not found')
+ return []
nft = json.loads(nft)
chain_list = []
diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login.py
index dbd346fe4..e26b81e3d 100755
--- a/src/conf_mode/system-login.py
+++ b/src/conf_mode/system-login.py
@@ -257,6 +257,15 @@ def apply(login):
except Exception as e:
raise ConfigError(f'Adding user "{user}" raised exception: "{e}"')
+ # Generate 2FA/MFA One-Time-Pad configuration
+ if dict_search('authentication.otp.key', user_config):
+ render(f'{home_dir}/.google_authenticator', 'login/pam_otp_ga.conf.j2',
+ user_config, permission=0o400, user=user, group='users')
+ else:
+ # delete configuration as it's not enabled for the user
+ if os.path.exists(f'{home_dir}/.google_authenticator'):
+ os.remove(f'{home_dir}/.google_authenticator')
+
if 'rm_users' in login:
for user in login['rm_users']:
try:
diff --git a/src/etc/sudoers.d/vyos b/src/etc/sudoers.d/vyos
index f760b417f..e0fd8cb0b 100644
--- a/src/etc/sudoers.d/vyos
+++ b/src/etc/sudoers.d/vyos
@@ -40,10 +40,13 @@ Cmnd_Alias PCAPTURE = /usr/bin/tcpdump
Cmnd_Alias HWINFO = /usr/bin/lspci
Cmnd_Alias FORCE_CLUSTER = /usr/share/heartbeat/hb_takeover, \
/usr/share/heartbeat/hb_standby
+Cmnd_Alias DIAGNOSTICS = /bin/ip vrf exec * /bin/ping *, \
+ /bin/ip vrf exec * /bin/traceroute *, \
+ /usr/libexec/vyos/op_mode/*
%operator ALL=NOPASSWD: DATE, IPTABLES, ETHTOOL, IPFLUSH, HWINFO, \
PPPOE_CMDS, PCAPTURE, /usr/sbin/wanpipemon, \
DMIDECODE, DISK, CONNTRACK, IP6TABLES, \
- FORCE_CLUSTER
+ FORCE_CLUSTER, DIAGNOSTICS
# Allow any user to run files in sudo-users
%users ALL=NOPASSWD: /opt/vyatta/bin/sudo-users/
diff --git a/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py b/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py
index cbc2bfe6b..d7eca5894 100755
--- a/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py
+++ b/src/etc/telegraf/custom_scripts/show_firewall_input_filter.py
@@ -11,7 +11,10 @@ def get_nft_filter_chains():
"""
Get list of nft chains for table filter
"""
- nft = cmd('/usr/sbin/nft --json list table ip vyos_filter')
+ try:
+ nft = cmd('/usr/sbin/nft --json list table ip vyos_filter')
+ except Exception:
+ return []
nft = json.loads(nft)
chain_list = []
diff --git a/src/op_mode/ipsec.py b/src/op_mode/ipsec.py
index a4d1b4cb1..7ec35d7bd 100755
--- a/src/op_mode/ipsec.py
+++ b/src/op_mode/ipsec.py
@@ -133,14 +133,13 @@ def _get_formatted_output_sas(sas):
def get_peer_connections(peer, tunnel, return_all = False):
- peer = peer.replace(':', '-')
- search = rf'^[\s]*(peer_{peer}_(tunnel_[\d]+|vti)).*'
+ search = rf'^[\s]*({peer}-(tunnel-[\d]+|vti)).*'
matches = []
with open(SWANCTL_CONF, 'r') as f:
for line in f.readlines():
result = re.match(search, line)
if result:
- suffix = f'tunnel_{tunnel}' if tunnel.isnumeric() else tunnel
+ suffix = f'tunnel-{tunnel}' if tunnel.isnumeric() else tunnel
if return_all or (result[2] == suffix):
matches.append(result[1])
return matches
diff --git a/src/services/vyos-http-api-server b/src/services/vyos-http-api-server
index 190f3409d..4ace981ca 100755
--- a/src/services/vyos-http-api-server
+++ b/src/services/vyos-http-api-server
@@ -686,10 +686,16 @@ if __name__ == '__main__':
app.state.vyos_keys = server_config['api_keys']
app.state.vyos_debug = server_config['debug']
- app.state.vyos_gql = server_config['gql']
- app.state.vyos_introspection = server_config['introspection']
app.state.vyos_strict = server_config['strict']
- app.state.vyos_origins = server_config.get('cors', {}).get('origins', [])
+ app.state.vyos_origins = server_config.get('cors', {}).get('allow_origin', [])
+ if 'gql' in server_config:
+ app.state.vyos_gql = True
+ if isinstance(server_config['gql'], dict) and 'introspection' in server_config['gql']:
+ app.state.vyos_introspection = True
+ else:
+ app.state.vyos_introspection = False
+ else:
+ app.state.vyos_gql = False
if app.state.vyos_gql:
graphql_init(app)