#!/usr/bin/env bash # NACM recovery user and credentials for internal mode # Use read-only NACM as use-case, ie to be able to break a deadlock and access # the config even though NACM is enabled and write is DENY # Only use netconf - restconf also has authentication on web level, and that gets # another layer # Main test default except mode, it gets too complicated otherwise # # Magic line must be first in script (see README.md) s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi APPNAME=example # Common NACM scripts . ./nacm.sh cfg=$dir/conf_yang.xml fyang=$dir/nacm-example.yang # cred:none, exact, except cat < $fyang module nacm-example{ yang-version 1.1; namespace "urn:example:nacm"; prefix nex; import clixon-example { prefix ex; } import ietf-netconf-acm { prefix nacm; } leaf x{ type int32; description "something to edit"; } } EOF # The groups are slightly modified from RFC8341 A.1 # The rule-list is from A.2 RULES='0truepermitpermitpermittrue' DEFAULT='truepermitdenypermittrue' # Arguments: # cred: none/exact/except # realuser: sudo/su as user, this is the real "peer" user # pseudo: mimic/run as user, this is the one sent in XML # recovery: recovery user # getp: true: get works; false: get does not work # putp: true: expected to work; false: not work testrun() { cred=$1 realuser=$2 pseudo=$3 recovery=$4 getp=$5 putp=$6 if [ "$realuser" = "root" ]; then prefix="sudo " else prefix="" fi cat < $cfg $cfg /usr/local/share/clixon $IETFRFC $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/restconf /usr/local/lib/$APPNAME/cli $APPNAME /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/lib/$APPNAME/backend /usr/local/var/$APPNAME/$APPNAME.pidfile /usr/local/var/$APPNAME false false $recovery internal $cred EOF if [ $BE -ne 0 ]; then sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg" start_backend -s init -f $cfg new "waiting" wait_backend fi if [ $RC -ne 0 ]; then new "kill old restconf daemon" stop_restconf_pre new "start restconf daemon (-a is enable basic authentication)" start_restconf -f $cfg -- -a new "waiting" wait_restconf fi if $getp; then # default is read allowed so this should always succeed. new "get startup default ok" expecteof "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 "]]>]]>" "^$DEFAULT]]>]]>$" # This would normally not work except in recovery situations else new "get startup not ok" expecteof "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 "]]>]]>" "^applicationaccess-deniederrorUser $realuser credential not matching NACM user $pseudo]]>]]>$" return; fi if $putp; then new "put, expect ok" expecteof "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 "$RULES]]>]]>" "]]>]]>" new "get rules ok" expecteof "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 ']]>]]>' "^$RULES]]>]]>$" else new "put, expect fail" expecteof "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 "$RULES]]>]]>" "^applicationaccess-deniederrordefault deny]]>]]>$" fi if [ $RC -ne 0 ]; then new "Kill restconf daemon" stop_restconf fi if [ $BE -ne 0 ]; then new "Kill backend" # Check if premature kill pid=$(pgrep -u root -f clixon_backend) if [ -z "$pid" ]; then err "backend already dead" fi # kill backend stop_backend -f $cfg fi } #------- CRED: except USER: non-root if [ "$USER" != root ]; then # Skip if USER is root # This is default, therefore first CRED=except REALUSER=$USER # Recovery as a seperate user does not work PSEUDO=$USER RECOVERY=_recovery new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY true false # Recovery as actual user works PSEUDO=$USER RECOVERY=$USER new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY true true # pseudo-user as recovery user does not work if actual user is non-root/non-web PSEUDO=_recovery RECOVERY=_recovery new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY false false PSEUDO=_recovery RECOVERY=$USER new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY false false fi # skip is USER is root #------- CRED: except USER: root CRED=except REALUSER=root # Recovery as a seperate user does not work PSEUDO=root RECOVERY=_recovery new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY true false # Recovery as actual user works PSEUDO=root RECOVERY=root new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY true true # pseudo-user as recovery user works IF cred=except AND realuser=root! PSEUDO=_recovery RECOVERY=_recovery new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY true true PSEUDO=_recovery RECOVERY=root new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY true false #------- CRED: none # Check you can use any pseudo user if cred is none CRED=none REALUSER=$USER PSEUDO=_recovery RECOVERY=_recovery new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY true true #------- CRED: exact # pseudo-user as recovery user does not work if cred=exact CRED=exact REALUSER=root PSEUDO=_recovery RECOVERY=_recovery new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY false false endtest rm -rf $dir