summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie Austin <jamiea@opusv.com.au>2023-01-26 16:34:36 +1100
committerJamie Austin <jamiea@opusv.com.au>2023-01-26 16:34:36 +1100
commit70794c8266ffefc6660daac3bc8a63b412d7b350 (patch)
treedc9b94123e3d68efafa63d63be54ca778ea99e9e
parent7634e16dcaaf4e08dec8bd9b92c6e731c32ef7cd (diff)
downloadvyos-1x-70794c8266ffefc6660daac3bc8a63b412d7b350.tar.gz
vyos-1x-70794c8266ffefc6660daac3bc8a63b412d7b350.zip
ocserv: T3896: add CLI options to configure ocserv config-per-user/group
Adds CLI configurations under VPN - OpenConnect to facilitate per user/group vpn session configurations. Validation has been added to restrict config-per-group to be exclusive to OpenConnect RADIUS authentication as the config file is looked up based on a RADIUS response attribute - as well as sanity check that the necessary configs are configured when not disabled.
-rw-r--r--data/templates/ocserv/ocserv_config.j215
-rw-r--r--interface-definitions/include/openconnect-config-per-x.xml.i54
-rw-r--r--interface-definitions/vpn-openconnect.xml.in1
-rwxr-xr-xsrc/conf_mode/vpn_openconnect.py11
4 files changed, 81 insertions, 0 deletions
diff --git a/data/templates/ocserv/ocserv_config.j2 b/data/templates/ocserv/ocserv_config.j2
index 3194354e6..ea2c9e29f 100644
--- a/data/templates/ocserv/ocserv_config.j2
+++ b/data/templates/ocserv/ocserv_config.j2
@@ -12,6 +12,14 @@ run-as-group = daemon
{% if "radius" in authentication.mode %}
auth = "radius [config=/run/ocserv/radiusclient.conf{{ ',groupconfig=true' if authentication.radius.groupconfig is vyos_defined else '' }}]"
+{% if "config_per_x" in authentication %}
+{% if authentication.config_per_x.disabled is not vyos_defined %}
+{% if "group" in authentication.config_per_x.mode %}
+config-per-group = {{ authentication.config_per_x.directory }}
+default-group-config = {{ authentication.config_per_x.default_config }}
+{% endif %}
+{% endif %}
+{% endif %}
{% elif "local" in authentication.mode %}
{% if authentication.mode.local == "password-otp" %}
auth = "plain[passwd=/run/ocserv/ocpasswd,otp=/run/ocserv/users.oath]"
@@ -24,6 +32,13 @@ auth = "plain[/run/ocserv/ocpasswd]"
auth = "plain[/run/ocserv/ocpasswd]"
{% endif %}
+{% if "config_per_x" in authentication %}
+{% if "user" in authentication.config_per_x.mode %}
+config-per-user = {{ authentication.config_per_x.directory }}
+default-user-config = {{ authentication.config_per_x.default_config }}
+{% endif %}
+{% endif %}
+
{% if ssl.certificate is vyos_defined %}
server-cert = /run/ocserv/cert.pem
server-key = /run/ocserv/cert.key
diff --git a/interface-definitions/include/openconnect-config-per-x.xml.i b/interface-definitions/include/openconnect-config-per-x.xml.i
new file mode 100644
index 000000000..71bbdd68f
--- /dev/null
+++ b/interface-definitions/include/openconnect-config-per-x.xml.i
@@ -0,0 +1,54 @@
+<!-- include start from openconnect-config-per-x.xml.i -->
+<node name="config-per-x">
+ <properties>
+ <help>Configures ocserv to search the configured directory for a config file matching the Group name or username</help>
+ </properties>
+ <children>
+ <leafNode name="mode">
+ <properties>
+ <help>ocserv will ignore these configs if groupconfig is enabled TODO: explain this in better detail - need to make it clear this is in reference to the groupconfig vyos config that lives up one level from here</help>
+ <valueHelp>
+ <format>user</format>
+ <description>ocserv config file loaded by matching file in configured directory to the users username</description>
+ </valueHelp>
+ <valueHelp>
+ <format>group</format>
+ <description>ocserv config file loaded by matching RADIUS class attribute in the RADIUS server response to a file in the configured directory</description>
+ </valueHelp>
+ <constraint>
+ <regex>(user|group)</regex>
+ </constraint>
+ <constraintErrorMessage>Invalid config-per-x. Must be one of: user, group </constraintErrorMessage>
+ <completionHelp>
+ <list>user group</list>
+ </completionHelp>
+ </properties>
+ </leafNode>
+ <leafNode name="directory">
+ <properties>
+ <help>Child directory of /config/auth e.g. /config/auth/ocserv/config-per-user</help>
+ <valueHelp>
+ <format>filename</format>
+ <description>Child directory of /config/auth e.g. /config/auth/ocserv/config-per-user</description>
+ </valueHelp>
+ <constraint>
+ <validator name="file-path" argument="--directory --parent-dir /config/auth --strict"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="default-config">
+ <properties>
+ <help>Default/fallback config to use when a file cannot be found in the configured directory that matches the username/group</help>
+ <valueHelp>
+ <format>filename</format>
+ <description>Child directory of /config/auth e.g. /config/auth/ocserv/defaults/user.conf</description>
+ </valueHelp>
+ <constraint>
+ <validator name="file-path" argument="--file --parent-dir /config/auth --strict"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ #include <include/generic-disable-node.xml.i>
+ </children>
+</node>
+<!-- include end --> \ No newline at end of file
diff --git a/interface-definitions/vpn-openconnect.xml.in b/interface-definitions/vpn-openconnect.xml.in
index 82fe2bbc9..24d24568f 100644
--- a/interface-definitions/vpn-openconnect.xml.in
+++ b/interface-definitions/vpn-openconnect.xml.in
@@ -50,6 +50,7 @@
</leafNode>
</children>
</node>
+ #include <include/openconnect-config-per-x.xml.i>
<leafNode name="group">
<properties>
<help>Group that a client is allowed to select (from a list). Maps to RADIUS Class attribute.</help>
diff --git a/src/conf_mode/vpn_openconnect.py b/src/conf_mode/vpn_openconnect.py
index af3c51efc..12165a4f2 100755
--- a/src/conf_mode/vpn_openconnect.py
+++ b/src/conf_mode/vpn_openconnect.py
@@ -113,6 +113,17 @@ def verify(ocserv):
users_wo_pswd.append(user)
if users_wo_pswd:
raise ConfigError(f'password required for users:\n{users_wo_pswd}')
+ # Validate that if config-per-x is configured all child config nodes are set
+ if 'config_per_x' in ocserv["authentication"]:
+ if 'disabled' not in ocserv["authentication"]["config_per_x"]:
+ if 'mode' not in ocserv["authentication"]["config_per_x"]:
+ raise ConfigError('OpenConnect radius config-per-x enabled but mode not selected')
+ elif 'group' in ocserv["authentication"]["config_per_x"]["mode"] and "radius" not in ocserv["authentication"]["mode"]:
+ raise ConfigError('OpenConnect config-per-group must be used with radius authentication')
+ if 'directory' not in ocserv["authentication"]["config_per_x"]:
+ raise ConfigError('OpenConnect config-per-x enabled but directory not set')
+ if 'default_config' not in ocserv["authentication"]["config_per_x"]:
+ raise ConfigError('OpenConnect config-per-x enabled but default-config not set')
else:
raise ConfigError('openconnect authentication mode required')
else: