clixon/test/test_nacm_datanode_read.sh
2024-05-28 19:44:38 +02:00

307 lines
10 KiB
Bash
Executable file

#!/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
# Define default restconfig config: RESTCONFIG
RESTCONFIG=$(restconf_config user false)
if [ $? -ne 0 ]; then
err1 "Error when generating certs"
fi
cat <<EOF > $cfg
<clixon-config xmlns="http://clicon.org/config">
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>${YANG_INSTALLDIR}</CLICON_YANG_DIR>
<CLICON_YANG_DIR>$dir</CLICON_YANG_DIR>
<CLICON_YANG_MAIN_FILE>$fyang</CLICON_YANG_MAIN_FILE>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_RESTCONF_DIR>/usr/local/lib/$APPNAME/restconf</CLICON_RESTCONF_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
<CLICON_SOCK>/usr/local/var/run/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_DIR>/usr/local/lib/$APPNAME/backend</CLICON_BACKEND_DIR>
<CLICON_BACKEND_PIDFILE>/usr/local/var/run/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
<CLICON_NACM_MODE>internal</CLICON_NACM_MODE>
<CLICON_NACM_DISABLED_ON_EMPTY>true</CLICON_NACM_DISABLED_ON_EMPTY>
$RESTCONFIG
</clixon-config>
EOF
cat <<EOF > $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{
presence "Tests rely on empty table";
container parameters{
list parameter{
key name;
leaf name{
type string;
}
leaf value{
type string;
}
}
}
}
container other{
leaf value{
type string;
}
}
}
EOF
cat <<EOF > $fyang2
module nacm-example2{
yang-version 1.1;
namespace "urn:example:nacm2";
prefix ex2;
container other2{
leaf value{
type string;
}
}
}
EOF
RULES=$(cat <<EOF
<nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
<enable-nacm>false</enable-nacm>
<read-default>deny</read-default>
<write-default>deny</write-default>
<exec-default>permit</exec-default>
$NGROUPS
<rule-list>
<name>limited-acl</name>
<group>limited</group>
<rule>
<name>parameter</name>
<module-name>*</module-name>
<access-operations>read</access-operations>
<path xmlns:ex="urn:example:nacm">/ex:table/ex:parameters/ex:parameter</path>
<action>permit</action>
</rule>
<rule>
<name>table</name>
<module-name>*</module-name>
<access-operations>read</access-operations>
<path xmlns:ex="urn:example:nacm">/ex:table</path>
<action>permit</action>
</rule>
<rule>
<name>module</name>
<module-name>nacm-example</module-name>
<access-operations>read</access-operations>
<action>permit</action>
</rule>
</rule-list>
$NADMIN
</nacm>
EOF
)
CONFIG=$(cat <<EOF
<table xmlns="urn:example:nacm">
<parameters>
<parameter>
<name>a</name>
<value>72</value>
</parameter>
</parameters>
</table>
<other xmlns="urn:example:nacm">
<value>99</value>
</other>
<other2 xmlns="urn:example:nacm2">
<value>88</value>
</other2>
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
function 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 $CURLOPTS -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/$HVER 204"
new "set module rule $module"
expectpart "$(curl -u andy:bar $CURLOPTS -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/$HVER 204"
new "set table rule $table"
expectpart "$(curl -u andy:bar $CURLOPTS -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/$HVER 204"
new "set parameter rule $parameter"
expectpart "$(curl -u andy:bar $CURLOPTS -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/$HVER 204"
#--------------- Here check
new "get other module"
if $test1; then
expectpart "$(curl -u wilma:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/nacm-example2:other2/value)" 0 "HTTP/$HVER 200" '{"nacm-example2:value":"88"}'
else
expectpart "$(curl -u wilma:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/nacm-example2:other2/value)" 0 "HTTP/$HVER 404" '{"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 $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/nacm-example:other/value)" 0 "HTTP/$HVER 200" '{"nacm-example:value":"99"}'
else
expectpart "$(curl -u wilma:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/nacm-example:other/value)" 0 "HTTP/$HVER 404" '{"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 $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/nacm-example:table?depth=1)" 0 "HTTP/$HVER 200" '{"nacm-example:table":{}}'
else
expectpart "$(curl -u wilma:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/nacm-example:table?depth=1)" 0 "HTTP/$HVER 404" '{"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 $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/nacm-example:table/parameters/parameter=a)" 0 "HTTP/$HVER 200" '{"nacm-example:parameter":\[{"name":"a","value":"72"}\]}'
else
expectpart "$(curl -u wilma:bar $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/nacm-example:table/parameters/parameter=a)" 0 "HTTP/$HVER 404" '{"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 "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
new "auth set authentication config"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$RULES</config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
new "set app config"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><edit-config><target><candidate/></target><config>$CONFIG</config></edit-config></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
new "commit it"
expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" "<rpc $DEFAULTNS><commit/></rpc>" "" "<rpc-reply $DEFAULTNS><ok/></rpc-reply>"
new "enable nacm"
expectpart "$(curl -u andy:bar $CURLOPTS -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/$HVER 204"
#--------------- 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
new "endtest"
endtest