#!/usr/bin/env bash # Authentication and authorization and IETF NACM # NACM module rules # A module rule has the "module-name" leaf set but no nodes from the # "rule-type" choice set. # @see test_nacm.sh is slightly modified - this follows the RFC more closely # See RFC 8341 A.1 and A.2 # Note: use clixon-example instead of ietf-netconf-monitoring since the latter is # 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 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 internal none EOF 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 ($USER added in admin group) # The rule-list is from A.2 RULES=$(cat < false deny deny deny $NGROUPS guest-acl guest permit-read clixon-example * deny Do not allow guests any access to the NETCONF monitoring information. limited-acl limited permit-ncm clixon-example read permit Allow read access to the NETCONF monitoring information. permit-exec * exec permit Allow invocation of the supported server operations. $NADMIN 42 key42val42 key43val43 EOF ) # NOTE use of translate^ has nothing to do with the CLI translate semantics CONFUSING! new "test params: -f $cfg -- -s" if [ $BE -ne 0 ]; then new "kill old backend" sudo clixon_backend -zf $cfg if [ $? -ne 0 ]; then err fi new "start backend -s init -f $cfg -- -s" start_backend -s init -f $cfg -- -s fi new "waiting" wait_backend if [ $RC -ne 0 ]; then new "kill old restconf daemon" sudo pkill -u $wwwuser -f clixon_restconf new "start restconf daemon (-a is enable basic authentication)" start_restconf -f $cfg -- -a new "waiting" wait_restconf fi new "auth set authentication config" expecteof "$clixon_netconf -qf $cfg" 0 "$RULES]]>]]>" "^]]>]]>$" new "commit it" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "enable nacm" expectpart "$(curl -u andy:bar -siS -X PUT -H "Content-Type: application/yang-data+json" -d '{"ietf-netconf-acm:enable-nacm": true}' http://localhost/restconf/data/ietf-netconf-acm:nacm/enable-nacm)" 0 "HTTP/1.1 204 No Content" #--------------- nacm enabled #----READ access #user:admin new "admin read ok" expectpart "$(curl -u andy:bar -siS -X GET http://localhost/restconf/data/clixon-example:translate)" 0 'HTTP/1.1 200 OK' '{"clixon-example:translate":{"translate":\[{"k":"key42","value":"val42"},{"k":"key43","value":"val43"}\]}}' new "admin read netconf ok" expecteof "$clixon_netconf -U andy -qf $cfg" 0 ']]>]]>' '^key42val42key43val43]]>]]>$' new "admin read element ok" expectpart "$(curl -u andy:bar -siS -X GET http://localhost/restconf/data/clixon-example:translate/translate=key42/value)" 0 'HTTP/1.1 200 OK' '{"clixon-example:value":"val42"}' new "admin read other module OK" expectpart "$(curl -u andy:bar -siS -X GET http://localhost/restconf/data/nacm-example:x)" 0 'HTTP/1.1 200 OK' '{"nacm-example:x":42}' new "admin read state OK" expectpart "$(curl -u andy:bar -siS -X GET http://localhost/restconf/data/clixon-example:state)" 0 'HTTP/1.1 200 OK' '{"clixon-example:state":{"op":\["41","42","43"\]}}' new "admin read top ok (all)" ret=$(curl -u andy:bar -sS -X GET http://localhost/restconf/data) expect='{"data":{"nacm-example:x":42,"clixon-example:translate":' match=`echo $ret | grep --null -Eo "$expect"` if [ -z "$match" ]; then err "$expect" "$ret" fi #user:limit new "limit read ok" expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/clixon-example:translate)" 0 'HTTP/1.1 200 OK' '{"clixon-example:translate":{"translate":\[{"k":"key42","value":"val42"},{"k":"key43","value":"val43"}\]}}' new "limit read netconf ok" expecteof "$clixon_netconf -U wilma -qf $cfg" 0 ']]>]]>' '^key42val42key43val43]]>]]>$' new "limit read element ok" expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/clixon-example:translate/translate=key42/value)" 0 'HTTP/1.1 200 OK' '{"clixon-example:value":"val42"}' new "limit read other module fail" expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/nacm-example:x)" 0 'HTTP/1.1 404 Not Found' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"invalid-value","error-severity":"error","error-message":"Instance does not exist"}}}' new "limit read state OK" expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/clixon-example:state)" 0 'HTTP/1.1 200 OK' '{"clixon-example:state":{"op":\["41","42","43"\]}}' new "limit read top ok (part)" expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data)" 0 'HTTP/1.1 200 OK' '{"data":{"clixon-example:translate":{"translate":\[{"k":"key42","value":"val42"},{"k":"key43","value":"val43"}\]},"clixon-example:state":{"op":\["41","42","43"\]}}}' #user:guest new "guest read forbidden" expectpart "$(curl -u guest:bar -siS -X GET http://localhost/restconf/data/clixon-example:translate)" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}' new "guest read netconf fail" expecteof "$clixon_netconf -U guest -qf $cfg" 0 ']]>]]>' '^applicationaccess-deniederrordefault deny]]>]]>$' new "guest read element forbidden" expectpart "$(curl -u guest:bar -siS -X GET http://localhost/restconf/data/clixon-example:translate/translate=key42/value)" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}' new "guest read other module fail" expectpart "$(curl -u guest:bar -siS -X GET http://localhost/restconf/data/nacm-example:x)" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}' new "guest read state fail" expectpart "$(curl -u guest:bar -siS -X GET http://localhost/restconf/data/clixon-example:state)" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}' new "guest read top ok (part)" expectpart "$(curl -u guest:bar -siS -X GET http://localhost/restconf/data)" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}' #------- RPC operation new "admin rpc ok" expectpart "$(curl -u andy:bar -si -X POST -H "Content-Type: application/yang-data+json" -d '{"clixon-example:input":{"x":"78"}}' http://localhost/restconf/operations/clixon-example:example)" 0 'HTTP/1.1 200 OK' '{"clixon-example:output":{"x":"78","y":"42"}}' new "admin rpc netconf ok" expecteof "$clixon_netconf -U andy -qf $cfg" 0 '0]]>]]>' 0 '^042]]>]]>$' new "limit rpc ok" expectpart "$(curl -u wilma:bar -si -X POST http://localhost/restconf/operations/clixon-example:example -H "Content-Type: application/yang-data+json" -d '{"clixon-example:input":{"x":42}}' )" 0 'HTTP/1.1 200 OK' '{"clixon-example:output":{"x":"42","y":"42"}}' new "limit rpc netconf ok" expecteof "$clixon_netconf -U wilma -qf $cfg" 0 '0]]>]]>' 0 '^042]]>]]>$' new "guest rpc fail" expectpart "$(curl -u guest:bar -si -X POST http://localhost/restconf/operations/clixon-example:example -H "Content-Type: application/yang-data+json" -d '{"clixon-example:input":{"x":42}}' )" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"access denied"}}}' new "guest rpc netconf fail" expecteof "$clixon_netconf -U guest -qf $cfg" 0 '0]]>]]>' 0 '^applicationaccess-deniederroraccess denied]]>]]>$' #------------------ Set read-default permit new "admin set read-default permit" expectpart "$(curl -u andy:bar -siS -X PUT -H "Content-Type: application/yang-data+json" -d '{"ietf-netconf-acm:read-default":"permit"}' http://localhost/restconf/data/ietf-netconf-acm:nacm/read-default)" 0 'HTTP/1.1 204 No Content' new "limit read ok" expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/clixon-example:translate)" 0 'HTTP/1.1 200 OK' '{"clixon-example:translate":{"translate":\[{"k":"key42","value":"val42"},{"k":"key43","value":"val43"}\]}}' new "limit read other module ok" expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/nacm-example:x)" 0 'HTTP/1.1 200 OK' '{"nacm-example:x":42}' new "guest read state fail" expectpart "$(curl -u guest:bar -siS -X GET http://localhost/restconf/data/clixon-example:state)" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}' if [ $RC -ne 0 ]; then new "Kill restconf daemon" stop_restconf fi if [ $BE -eq 0 ]; then exit # BE fi 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 rm -rf $dir