diff options
author | Christian Poessinger <christian@poessinger.com> | 2020-02-02 18:40:14 +0100 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2020-02-05 19:35:13 +0100 |
commit | 3a64047c2f1b6279de4b1ada7e87aa5c871f5604 (patch) | |
tree | b964b610dd8dd4133d1f2b1f282f12a12afa1d41 /src | |
parent | 9c52edb9e2079c315af7385a85f61f21138dd5a6 (diff) | |
download | vyos-1x-3a64047c2f1b6279de4b1ada7e87aa5c871f5604.tar.gz vyos-1x-3a64047c2f1b6279de4b1ada7e87aa5c871f5604.zip |
ogin: user: radius: T1948: use discrete configuration for each system
Split combined XML/Python code to individual code for local user accounts
and RADIUS authenticated accounts.
Diffstat (limited to 'src')
-rwxr-xr-x | src/conf_mode/system-login-radius.py | 138 | ||||
-rwxr-xr-x | src/conf_mode/system-login-user.py (renamed from src/conf_mode/system-login.py) | 92 |
2 files changed, 146 insertions, 84 deletions
diff --git a/src/conf_mode/system-login-radius.py b/src/conf_mode/system-login-radius.py new file mode 100755 index 000000000..8f5d7bc36 --- /dev/null +++ b/src/conf_mode/system-login-radius.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2020 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 os +import jinja2 + +from pwd import getpwall, getpwnam +from stat import S_IRUSR, S_IWUSR + +from vyos.config import Config +from vyos.configdict import list_diff +from vyos import ConfigError + +radius_config_file = "/etc/pam_radius_auth.conf" +radius_config_tmpl = """ +# Automatically generated by VyOS +# RADIUS configuration file +# server[:port] shared_secret timeout (s) source_ip +{% if server -%} +{% for s in server -%} +{{ s.address }}:{{ s.port }} {{ s.key }} {{ s.timeout }} {% if source_address -%}{{ source_address }}{% endif %} +{% endfor -%} + +priv-lvl 15 +mapped_priv_user radius_priv_user +{% endif %} + +""" + +default_config_data = { + 'server': [], + 'source_address': '', +} + +def get_local_users(): + """Returns list of dynamically allocated users (see Debian Policy Manual)""" + local_users = [] + for p in getpwall(): + username = p[0] + uid = getpwnam(username).pw_uid + if uid in range(1000, 29999): + if username not in ['radius_user', 'radius_priv_user']: + local_users.append(username) + + return local_users + +def get_config(): + radius = default_config_data + conf = Config() + base_level = ['system', 'login', 'radius'] + + if not conf.exists(base_level): + return radius + + conf.set_level(base_level) + + if conf.exists(['source-address']): + radius['source_address'] = conf.return_value(['source-address']) + + # Read in all RADIUS servers and store to list + for server in conf.list_nodes(['server']): + radius = { + 'address': server, + 'key': '', + 'port': '1812', + 'timeout': '2' + } + conf.set_level(base_level + ['server', server]) + + # RADIUS shared secret + if conf.exists(['key']): + radius['key'] = conf.return_value(['key']) + + # RADIUS authentication port + if conf.exists(['port']): + radius['port'] = conf.return_value(['port']) + + # RADIUS session timeout + if conf.exists(['timeout']): + radius['timeout'] = conf.return_value(['timeout']) + + # Append individual RADIUS server configuration to global server list + radius['server'].append(radius) + + return radius + +def verify(radius): + pass + +def generate(radius): + if len(radius['server']) > 0: + tmpl = jinja2.Template(radius_config_tmpl) + config_text = tmpl.render(radius) + with open(radius_config_file, 'w') as f: + f.write(config_text) + + uid = getpwnam('root').pw_uid + gid = getpwnam('root').pw_gid + os.chown(radius_config_file, uid, gid) + os.chmod(radius_config_file, S_IRUSR | S_IWUSR) + else: + os.unlink(radius_config_file) + + return None + +def apply(radius): + if len(radius['server']) > 0: + # Enable RADIUS in PAM + os.system("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --enable radius") + else: + # Disable RADIUS in PAM + os.system("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --remove radius") + + return None + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + sys.exit(1) diff --git a/src/conf_mode/system-login.py b/src/conf_mode/system-login-user.py index 4f741d121..3317f87d8 100755 --- a/src/conf_mode/system-login.py +++ b/src/conf_mode/system-login-user.py @@ -16,10 +16,8 @@ import sys import os -import jinja2 from pwd import getpwall, getpwnam -from grp import getgrnam from stat import S_IRUSR, S_IWUSR, S_IRWXU, S_IRGRP, S_IXGRP from subprocess import Popen, PIPE, STDOUT @@ -27,26 +25,8 @@ from vyos.config import Config from vyos.configdict import list_diff from vyos import ConfigError -radius_config_file = "/etc/pam_radius_auth.conf" -radius_config_tmpl = """ -# Automatically generated by VyOS -# RADIUS configuration file -# server[:port] shared_secret timeout (s) source_ip -{% if radius_server -%} -{% for s in radius_server -%} -{{ s.address }}:{{ s.port }} {{ s.key }} {{ s.timeout }} {% if radius_source -%}{{ radius_source }}{% endif %} -{% endfor -%} - -priv-lvl 15 -mapped_priv_user radius_priv_user -{% endif %} - -""" - default_config_data = { 'deleted': False, - 'radius_server': [], - 'radius_source': '', 'add_users': [], 'del_users': [] } @@ -63,54 +43,25 @@ def get_local_users(): return local_users + def get_crypt_pw(password): command = '/usr/bin/mkpasswd --method=sha-512 {}'.format(password) p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True) tmp = p.communicate()[0].strip() return tmp.decode() + def get_config(): login = default_config_data conf = Config() - base_level = ['system', 'login'] + base_level = ['system', 'login', 'user'] if not conf.exists(base_level): login['deleted'] = True return login - conf.set_level(base_level) - - if conf.exists(['radius', 'source-address']): - login['radius_source'] = conf.return_value(['radius', 'source-address']) - - # Read in all RADIUS servers and store to list - for server in conf.list_nodes(['radius', 'server']): - radius = { - 'address': server, - 'key': '', - 'port': '1812', - 'timeout': '2' - } - conf.set_level(base_level + ['radius', 'server', server]) - - # RADIUS shared secret - if conf.exists(['key']): - radius['key'] = conf.return_value(['key']) - - # RADIUS authentication port - if conf.exists(['port']): - radius['port'] = conf.return_value(['port']) - - # RADIUS session timeout - if conf.exists(['timeout']): - radius['timeout'] = conf.return_value(['timeout']) - - # Append individual RADIUS server configuration to global server list - login['radius_server'].append(radius) - # Read in all local users and store to list - conf.set_level(base_level) - for username in conf.list_nodes(['user']): + for username in conf.list_nodes(base_level): user = { 'name': username, 'password_plaintext': '', @@ -119,7 +70,7 @@ def get_config(): 'full_name': '', 'home_dir': '/home/' + username, } - conf.set_level(base_level + ['user', username]) + conf.set_level(base_level + [username]) # Plaintext password if conf.exists(['authentication', 'plaintext-password']): @@ -145,7 +96,7 @@ def get_config(): 'options': '', 'type': '' } - conf.set_level(base_level + ['user', username, 'authentication', 'public-keys', id]) + conf.set_level(base_level + [username, 'authentication', 'public-keys', id]) # Public Key portion if conf.exists(['key']): @@ -164,7 +115,6 @@ def get_config(): login['add_users'].append(user) - return login def verify(login): @@ -193,23 +143,7 @@ def generate(login): os.system("vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set system login user '{}' authentication plaintext-password '' >/dev/null".format(user['name'])) os.system("vyos_libexec_dir=/usr/libexec/vyos /opt/vyatta/sbin/my_set system login user '{}' authentication encrypted-password '{}' >/dev/null".format(user['name'], user['password_encrypted'])) - # - # RADIUS - # - if len(login['radius_server']) > 0: - tmpl = jinja2.Template(radius_config_tmpl) - config_text = tmpl.render(login) - with open(radius_config_file, 'w') as f: - f.write(config_text) - - uid = getpwnam('root').pw_uid - gid = getpwnam('root').pw_gid - os.chown(radius_config_file, uid, gid) - os.chmod(radius_config_file, S_IRUSR | S_IWUSR) - else: - os.unlink(radius_config_file) - - pass + return None def apply(login): for user in login['add_users']: @@ -272,17 +206,7 @@ def apply(login): except Exception as e: print('Deleting user "{}" raised an exception'.format(user)) - # - # RADIUS - # - if len(login['radius_server']) > 0: - # Enable RADIUS in PAM - os.system("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --enable radius") - else: - # Disable RADIUS in PAM - os.system("DEBIAN_FRONTEND=noninteractive pam-auth-update --package --remove radius") - - pass + return None if __name__ == '__main__': try: |