diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/system_login.py | 39 | ||||
| -rw-r--r-- | src/opt/vyatta/share/vyatta-op/functions/interpreter/vyatta-op-run | 18 |
2 files changed, 54 insertions, 3 deletions
diff --git a/src/conf_mode/system_login.py b/src/conf_mode/system_login.py index 234b24770..c2562be7b 100755 --- a/src/conf_mode/system_login.py +++ b/src/conf_mode/system_login.py @@ -14,7 +14,9 @@ # 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 re import os +import json from passlib.hosts import linux_context from psutil import users @@ -171,6 +173,15 @@ def verify(login): if 'key' not in pubkey_options: raise ConfigError(f'Missing key for public-key "{pubkey}"!') + if 'operator' in user_config: + op_groups = dict_search('operator.group', user_config) + if op_groups: + for og in op_groups: + if dict_search(f'operator_group.{og}', login) is None: + raise ConfigError(f'Operator group {og} does not exist') + else: + raise ConfigError(f'User {user} is configured as an operator but is not assigned to any operator groups') + if {'radius', 'tacacs'} <= set(login): raise ConfigError('Using both RADIUS and TACACS at the same time is not supported!') @@ -306,6 +317,28 @@ def generate(login): if os.path.isfile(autologout_file): os.unlink(autologout_file) + # Operator groups and group membership + operator_config = {'users': {}, 'groups': {}} + if 'user' in login: + for user, user_config in login['user'].items(): + op_groups = dict_search('operator.group', user_config) + if op_groups: + operator_config['users'][user] = op_groups + + if 'operator_group' in login: + operator_config['groups'] = login['operator_group'] + + # Convert permissions strings to list + # so that the operational command runner doesn't have to + for g in operator_config['groups']: + policy = dict_search(f'command_policy.allow', operator_config['groups'][g]) + if policy is not None: + policy = list(map(lambda s: re.split(r'\s+', s), policy)) + operator_config['groups'][g]['command_policy']['allow'] = policy + + with open('/etc/vyos/operators.json', 'w') as of: + json.dump(operator_config, of) + return None @@ -335,7 +368,11 @@ def apply(login): if tmp: command += f" --home '{tmp}'" else: command += f" --home '/home/{user}'" - command += f' --groups frr,frrvty,vyattacfg,sudo,adm,dip,disk,_kea {user}' + if 'operator' not in user_config: + command += f' --groups frr,frrvty,vyattacfg,sudo,adm,dip,disk,_kea' + + command += f' {user}' + try: cmd(command) # we should not rely on the value stored in user_config['home_directory'], as a diff --git a/src/opt/vyatta/share/vyatta-op/functions/interpreter/vyatta-op-run b/src/opt/vyatta/share/vyatta-op/functions/interpreter/vyatta-op-run index 6bc77b61d..f43c85fa9 100644 --- a/src/opt/vyatta/share/vyatta-op/functions/interpreter/vyatta-op-run +++ b/src/opt/vyatta/share/vyatta-op/functions/interpreter/vyatta-op-run @@ -217,6 +217,20 @@ _vyatta_op_run () local run_cmd=$(_vyatta_op_get_node_def_field $tpath/node.def run) run_cmd=$(_vyatta_op_conv_run_cmd "$run_cmd") # convert the positional parameters local ret=0 + + if groups "$(whoami)" | grep -q -E ' vyattacfg(\s|$)'; then + # If the user is an admin, + # use sudo directly for now + op_runner="sudo" + else + # If the user is an operator, + # use the new operational command runner + # (operator users have no sudo permissions) + # and give it the original VyOS command + op_runner="vyos-op-run" + run_cmd="$@" + fi + # Exception for the `show file` command local file_cmd='\$\{vyos_op_scripts_dir\}\/file\.py' local cmd_regex="^(LESSOPEN=|less|pager|tail|(sudo )?$file_cmd).*" @@ -234,9 +248,9 @@ _vyatta_op_run () # to be able to do their job. eval "$run_cmd" elif [[ -t 1 && "${args[1]}" == "show" && ! $run_cmd =~ $cmd_regex ]] ; then - eval "(sudo $run_cmd) | ${VYATTA_PAGER:-cat}" + eval "($op_runner $run_cmd) | ${VYATTA_PAGER:-cat}" else - eval "sudo $run_cmd" + eval "$op_runner $run_cmd" fi else echo -ne "\n Incomplete command: ${args[@]}\n\n" >&2 |
