#!/usr/bin/env bash # Restconf basic authentication tests as implemented by main example # Note this is not supported by core clixon: you need ca-auth callback implemented a la the example # For auth-type=none and auth-type=user, # For auth-type=ssl-certs, See test_restconf.sh test_restconf_ssl_certs.sh # native? and http only # Use the following user settings: # 1. none # 2. anonymous - the registered anonymous user # 3. andy - a well-known user # 3. unknown - unknown user # Use NACM to return XML for different returns for anonymous and andy # 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.xml # The anonymous user anonymous=myanonymous fyang=$dir/myexample.yang # No ssl RCPROTO=http HVER=1.1 # Start with common config, then append fcgi/native specific config cat < $cfg $cfg ietf-netconf:startup /usr/local/share/clixon $IETFRFC $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ /usr/local/lib/$APPNAME/restconf /usr/local/lib/$APPNAME/cli $APPNAME /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile $dir true true internal $anonymous EOF # There are two implicit modules defined by RFC 8341 # This is a try to define them cat < $fyang module myexample{ yang-version 1.1; namespace "urn:example:auth"; prefix ex; import ietf-netconf-acm { prefix nacm; } container top { leaf anonymous{ type string; } leaf wilma { type string; } } } EOF # NACM rules and top/ config cat < $dir/startup_db <${DATASTORE_TOP}> true deny deny deny anonymous $anonymous limited wilma admin root $USER data-anon anonymous allow-get ietf-netconf get exec permit allow-anon myexample * /ex:top/ex:anonymous permit data-limited limited allow-get ietf-netconf get exec permit allow-wilma myexample * /ex:top/ex:wilma permit $NADMIN 42 71 EOF # Restconf auth test with arguments: # 1. auth-type # 2: -u user:passwd or "" # 3: expectcode expected HTTP return code # 4: expectmsg top return JSON message # The return cases are: authentication permit/deny, authorization permit/deny # We use authorization returns here only to verify we got the right user in authentication. # Authentication ok/nok # permit: 200 or 403 # deny: 401 # The user replies are: # $anonymous: {"myexample:top":{"anonymous":"42"}} # wilma: {"myexample:top":{"wilma":"71"}} # unknown: retval 403 function testrun() { auth=$1 user=$2 expectcode=$3 expectmsg=$4 # echo "auth:$auth" # echo "user:$user" # echo "expectcode:$expectcode" # echo "expectmsg:$expectmsg" # Change restconf configuration before start restconf daemon RESTCONFIG=$(restconf_config $auth false) # Start with common config, then append fcgi/native specific config cat < $cfg $cfg ietf-netconf:startup clixon-restconf:allow-auth-none /usr/local/share/clixon $IETFRFC $fyang /usr/local/lib/$APPNAME/clispec /usr/local/lib/$APPNAME/backend example_backend.so$ /usr/local/lib/$APPNAME/restconf /usr/local/lib/$APPNAME/cli $APPNAME /usr/local/var/$APPNAME/$APPNAME.sock /usr/local/var/$APPNAME/$APPNAME.pidfile $dir true internal $anonymous $RESTCONFIG EOF 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 new "curl $CURLOPTS $user -X GET $RCPROTO://localhost/restconf/data/myexample:top" expectpart "$(curl $CURLOPTS $user -X GET $RCPROTO://localhost/restconf/data/myexample:top)" 0 $expectcode "$expectmsg" if [ $RC -ne 0 ]; then new "Kill restconf daemon" stop_restconf fi } if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi sudo pkill -f clixon_backend # to be sure new "start backend -s startup -f $cfg" start_backend -s startup -f $cfg fi new "wait backend" wait_backend MSGANON='{"myexample:top":{"anonymous":"42"}}' MSGWILMA='{"myexample:top":{"wilma":"71"}}' # Authentication failed: MSGERR1='{"ietf-restconf:errors":{"error":{"error-type":"protocol","error-tag":"access-denied","error-severity":"error","error-message":"The requested URL was unauthorized"}}}' # Authentication OK Authorization failed: MSGERR2='{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}' AUTH=none new "auth-type=$AUTH no user" testrun $AUTH "" "HTTP/$HPRE 200" "$MSGANON" # OK - anonymous new "auth-type=$AUTH anonymous" testrun $AUTH "-u ${anonymous}:foo" "HTTP/$HVER 200" "$MSGANON" # OK - anonymous new "auth-type=$AUTH wilma" testrun $AUTH "-u wilma:bar" "HTTP/$HVER 200" # OK - wilma new "auth-type=$AUTH wilma wrong passwd" testrun $AUTH "-u wilma:wrong" "HTTP/$HVER 200" "$MSGANON" # OK - wilma AUTH=user new "auth-type=$AUTH no user" testrun $AUTH "" "HTTP/$HVER 401" "$MSGERR1" # denied new "auth-type=$AUTH anonymous" testrun $AUTH "-u ${anonymous}:foo" "HTTP/$HVER 401" # denied new "auth-type=$AUTH wilma" testrun $AUTH "-u wilma:bar" "HTTP/$HVER 200" "$MSGWILMA" # OK - wilma new "auth-type=$AUTH wilma wrong passwd" testrun $AUTH "-u wilma:wrong" "HTTP/$HVER 401" "$MSGERR1" # denied new "auth-type=$AUTH unknown" testrun $AUTH "-u unknown:any" "HTTP/$HVER 401" "$MSGERR1" # denied 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 # unset conditional parameters unset RCPROTO unset RESTCONFIG1 unset MSGANON unset MSGWILMA unset MSGERR1 unset MSGERR2 rm -rf $dir new "endtest" endtest