#!/usr/bin/env bash # Authentication and authorization and IETF NACM # NACM data node rules # The RFC 8341 examples in the appendix are very limited. # Here focus on datanode paths from a read perspective. # The limit user is used for this # The following shows a tree of the paths where permit/deny actions can be set: # read-default # module # /table # /table/parameters/parameter # # The test goes through all permutations and checks the expected behaviour # # 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 fyang2=$dir/nacm-example2.yang cat < $cfg $cfg /usr/local/share/clixon $IETFRFC $dir $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 EOF cat < $fyang module nacm-example{ yang-version 1.1; namespace "urn:example:nacm"; prefix ex; import ietf-netconf-acm { prefix nacm; } import nacm-example2 { prefix ex2; } container table{ container parameters{ list parameter{ key name; leaf name{ type string; } leaf value{ type string; } } } } container other{ leaf value{ type string; } } } EOF cat < $fyang2 module nacm-example2{ yang-version 1.1; namespace "urn:example:nacm2"; prefix ex2; container other2{ leaf value{ type string; } } } EOF RULES=$(cat < false deny deny permit $NGROUPS limited-acl limited parameter * read /ex:table/ex:parameters/ex:parameter permit table * read /ex:table permit module nacm-example read permit $NADMIN EOF ) CONFIG=$(cat < a 72 99 88 EOF ) # # Arguments, permit/deny on different levels: # Configs (permit/deny): # - read-default # - module as a whole # - table: root symbol # - param: sub symbol # Tests, epxect true/false: # - read other module # - read other in same module # - read table # - read parameter testrun(){ readdefault=$1 module=$2 table=$3 parameter=$4 test1=$5 test2=$6 test3=$7 test4=$8 new "read-default:$readdefault module:$module table:$table parameter:$parameter" new "set read-default $readdefault" expectpart "$(curl -u andy:bar -sik -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/ietf-netconf-acm:nacm/read-default -d "{\"ietf-netconf-acm:read-default\":\"$readdefault\"}" )" 0 "HTTP/1.1 204 No Content" new "set module rule $module" expectpart "$(curl -u andy:bar -sik -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/ietf-netconf-acm:nacm/rule-list=limited-acl/rule=module/action -d "{\"ietf-netconf-acm:action\":\"$module\"}" )" 0 "HTTP/1.1 204 No Content" new "set table rule $table" expectpart "$(curl -u andy:bar -sik -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/ietf-netconf-acm:nacm/rule-list=limited-acl/rule=table/action -d "{\"ietf-netconf-acm:action\":\"$table\"}" )" 0 "HTTP/1.1 204 No Content" new "set parameter rule $parameter" expectpart "$(curl -u andy:bar -sik -X PUT -H "Content-Type: application/yang-data+json" $RCPROTO://localhost/restconf/data/ietf-netconf-acm:nacm/rule-list=limited-acl/rule=parameter/action -d "{\"ietf-netconf-acm:action\":\"$parameter\"}" )" 0 "HTTP/1.1 204 No Content" #--------------- Here check new "get other module" if $test1; then expectpart "$(curl -u wilma:bar -sik -X GET $RCPROTO://localhost/restconf/data/nacm-example2:other2/value)" 0 'HTTP/1.1 200 OK' '{"nacm-example2:value":"88"}' else expectpart "$(curl -u wilma:bar -sik -X GET $RCPROTO://localhost/restconf/data/nacm-example2:other2/value)" 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"}}}' fi new "get other in same module" if $test2; then expectpart "$(curl -u wilma:bar -sik -X GET $RCPROTO://localhost/restconf/data/nacm-example:other/value)" 0 'HTTP/1.1 200 OK' '{"nacm-example:value":"99"}' else expectpart "$(curl -u wilma:bar -sik -X GET $RCPROTO://localhost/restconf/data/nacm-example:other/value)" 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"}}}' fi new "get table" if $test3; then expectpart "$(curl -u wilma:bar -sik -X GET $RCPROTO://localhost/restconf/data/nacm-example:table?depth=1)" 0 'HTTP/1.1 200 OK' '{"nacm-example:table":{}}' else expectpart "$(curl -u wilma:bar -sik -X GET $RCPROTO://localhost/restconf/data/nacm-example:table?depth=1)" 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"}}}' fi new "get parameter" if $test4; then expectpart "$(curl -u wilma:bar -sik -X GET $RCPROTO://localhost/restconf/data/nacm-example:table/parameters/parameter=a)" 0 'HTTP/1.1 200 OK' '{"nacm-example:parameter":\[{"name":"a","value":"72"}\]}' else expectpart "$(curl -u wilma:bar -sik -X GET $RCPROTO://localhost/restconf/data/nacm-example:table/parameters/parameter=a)" 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"}}}' fi } # testrun new "test params: -f $cfg" 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" start_backend -s init -f $cfg fi new "waiting" wait_backend 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 new "auth set authentication config" expecteof "$clixon_netconf -qf $cfg" 0 "$RULES]]>]]>" "^]]>]]>$" new "set app config" expecteof "$clixon_netconf -qf $cfg" 0 "$CONFIG]]>]]>" "^]]>]]>$" new "commit it" expecteof "$clixon_netconf -qf $cfg" 0 "]]>]]>" "^]]>]]>$" new "enable nacm" expectpart "$(curl -u andy:bar -sik -X PUT -H "Content-Type: application/yang-data+json" -d '{"ietf-netconf-acm:enable-nacm": true}' $RCPROTO://localhost/restconf/data/ietf-netconf-acm:nacm/enable-nacm)" 0 "HTTP/1.1 204 No Content" #--------------- nacm enabled # config: def module table parameter # test: mod other table parameter # default deny testrun deny deny deny deny false false false false testrun deny deny deny permit false false false false testrun deny deny permit deny false false true false testrun deny deny permit permit false false true true testrun deny permit deny deny false true false false testrun deny permit deny permit false true false false testrun deny permit permit deny false true true false testrun deny permit permit permit false true true true # default permit testrun permit deny deny deny true false false false testrun permit deny deny permit true false false false testrun permit deny permit deny true false true false testrun permit deny permit permit true false true true testrun permit permit deny deny true true false false testrun permit permit deny permit true true false false testrun permit permit permit deny true true true false testrun permit permit permit permit true true true true if [ $RC -ne 0 ]; then new "Kill restconf daemon" stop_restconf fi if [ $BE -ne 0 ]; then # Bring your own backend 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 rm -rf $dir