#!/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 NACMUSER=$(whoami) # cred:none, exact, except # Define default restconfig config: RESTCONFIG RESTCONFIG=$(restconf_config user false) if [ $? -ne 0 ]; then err1 "Error when generating certs" fi cat < $fyang module nacm-example{ yang-version 1.1; namespace "urn:example:nacm"; prefix nex; 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 function 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 ${YANG_INSTALLDIR} $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/restconf /usr/local/lib/$APPNAME/cli $APPNAME /usr/local/var/run/$APPNAME.sock /usr/local/lib/$APPNAME/backend /usr/local/var/run/$APPNAME.pidfile /usr/local/var/$APPNAME false $recovery internal $cred $RESTCONFIG 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 fi new "wait backend" wait_backend if [ $RC -ne 0 ]; then new "kill old restconf daemon" stop_restconf_pre new "start restconf daemon" start_restconf -f $cfg fi new "wait restconf" wait_restconf if $getp; then # default is read allowed so this should always succeed. new "get startup default ok" expecteof_netconf "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 "$DEFAULTHELLO" "report-all" "" "$DEFAULT" # This would normally not work except in recovery situations else new "get startup not ok" expecteof_netconf "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 "$DEFAULTHELLO" "" "" "applicationaccess-deniederrorUser $realuser credential not matching NACM user $pseudo" fi if $putp; then new "put, expect ok" expecteof_netconf "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 "$DEFAULTHELLO" "$RULES" "" "" new "get rules ok" expecteof_netconf "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 "$DEFAULTHELLO" "" "" "$RULES" else new "put, expect fail" expecteof_netconf "$prefix$clixon_netconf -qf $cfg -U $pseudo" 0 "$DEFAULTHELLO" "$RULES" "applicationaccess-deniederror" "" # default 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 [ "$NACMUSER" != root ]; then # Skip if USER is root # This is default, therefore first CRED=except REALUSER=$NACMUSER # Recovery as a seperate user does not work PSEUDO=$NACMUSER RECOVERY=_recovery new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY true false # Recovery as actual user works PSEUDO=$NACMUSER RECOVERY=$NACMUSER 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=$NACMUSER new "cred: $CRED realuser:$REALUSER pseudo:$PSEUDO recovery:$RECOVERY" testrun $CRED $REALUSER $PSEUDO $RECOVERY false false fi # skip is NACMUSER is root #------- CRED: except NACMUSER: 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=$NACMUSER 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 new "endtest" endtest unset NACMUSER rm -rf $dir