diff --git a/CHANGELOG.md b/CHANGELOG.md index cb4278be..925c295d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,13 +76,16 @@ * Note CLIXON_DATADIR (=/usr/local/share/clixon) need to be in the list * CLICON_YANG_MAIN_FILE Provides a filename with a single module filename. * CLICON_YANG_MAIN_DIR Provides a directory where all yang modules should be loaded. -* NACM extension (RFC8341) - * NACM Data node READ and WRITE access module support (RFC8341 3.4.5) - * Access control points added for `get`, `get-config`, `edit-config` in addition to incoming rpc. - * RFC 8341 Example A.2 implemented, see: [test/test_nacm_module.sh] - * Remaining work: data-node PATH +* NACM (RFC8341) experimental + * Incoming RPC Message validation is supported (3.4.4) + * Data Node Access validation is supported (3.4.5), except: + * rule-type data-node path is not supported + * Outgoing noitification aithorization is _not_ supported (3.4.6) + * RPC:s are supported _except_: + * `copy-config`for other src/target combinations than running/startup (3.2.6) + * `commit` - NACM is applied to candidate and running operations only (3.2.8) + * Client-side RPC:s are _not_ supported. * Recovery user "_nacm_recovery" added. - * Example use is restconf PUT when NACM edit-config is permitted, then automatic commit and discard are permitted using recovery user. ### API changes on existing features (you may need to change your code) * Added `username` argument on `xmldb_put()` datastore function for NACM data-node write checks diff --git a/README.md b/README.md index 215ac2ea..a56aecc9 100644 --- a/README.md +++ b/README.md @@ -220,35 +220,28 @@ so the clients can in principle fake a username. NACM ==== -Clixon includes an experimental Network Configuration Access Control Model (NACM) according to [RFC8341(NACM)](https://tools.ietf.org/html/rfc8341). It has limited functionality. +Clixon includes an experimental Network Configuration Access Control Model (NACM) according to [RFC8341(NACM)](https://tools.ietf.org/html/rfc8341). -The support is as follows: +To enable NACM: -* There is a yang config variable `CLICON_NACM_MODE` to set whether NACM is disabled, uses internal(embedded) NACM configuration, or external configuration. (See yang/clixon-config.yang) -* If the mode is internal, NACM configurations is expected to be in the regular configuration, managed by regular candidate/runing/commit procedures. This mode may have some problems with bootstrapping. +* The `CLICON_NACM_MODE` config variable is by default `disabled`. +* If the mode is internal`, NACM configurations are expected to be in the regular configuration, managed by regular candidate/runing/commit procedures. This mode may have some problems with bootstrapping. * If the mode is `external`, the `CLICON_NACM_FILE` yang config variable contains the name of a separate configuration file containing the NACM configurations. After changes in this file, the backend needs to be restarted. -* The [example](example/README.md) contains a http basic auth and a NACM backend callback for mandatory state variables. -* There are two [tests](test/README.md) using internal and external NACM config -* The backend provides a limited NACM support (when enabled) described below -NACM is implemented in the backend and a single access check is made -in `from_client_msg()` when an internal netconf RPC has -just been received and decoded. The code is in `nacm_access()`. +The [example](example/README.md) contains a http basic auth and a NACM backend callback for mandatory state variables. -The functionality is as follows: -* Notification is not supported -* Groups are supported -* Rule-lists are supported -* Rules are supported as follows - * module-name: fully supported - * access-operations: only '*' and 'exec' supported - * rpc-name: fully supported (eg edit-config/get-config, etc) - * action: fully supported (permit/deny) +NACM is implemented in the backend with incoming RPC and data node access control points. -The tests outlines an example of three groups (taken from the RFC): admin, limited and guest: -* admin: Full access -* limited: Read access (get and get-config) -* guest: No access +The functionality is as follows (references to sections in [RFC8341](https://tools.ietf.org/html/rfc8341)): +* Access control point support: + * Incoming RPC Message validation is supported (3.4.4) + * Data Node Access validation is supported (3.4.5), except: + * rule-type data-node path is not supported + * Outgoing noitification aithorization is _not_ supported (3.4.6) +* RPC:s are supported _except_: + * `copy-config`for other src/target combinations than running/startup (3.2.6) + * `commit` - NACM is applied to candidate and running operations only (3.2.8) +* Client-side RPC:s are _not_ supported. Runtime ======= diff --git a/apps/backend/backend_client.c b/apps/backend/backend_client.c index 936f03f1..c2c370fe 100644 --- a/apps/backend/backend_client.c +++ b/apps/backend/backend_client.c @@ -214,7 +214,7 @@ from_client_get_config(clicon_handle h, goto ok; } /* Pre-NACM access step */ - if ((ret = nacm_access_h(h, username, &xnacm)) < 0) + if ((ret = nacm_access_pre(h, username, &xnacm)) < 0) goto done; if (ret == 0){ /* Do NACM validation */ if (xpath_vec(xret, "%s", &xvec, &xlen, xpath?xpath:"/") < 0) @@ -407,7 +407,7 @@ from_client_get(clicon_handle h, goto ok; } /* Pre-NACM access step */ - if ((ret = nacm_access_h(h, username, &xnacm)) < 0) + if ((ret = nacm_access_pre(h, username, &xnacm)) < 0) goto done; if (ret == 0){ /* Do NACM validation */ if (xpath_vec(xret, "%s", &xvec, &xlen, xpath?xpath:"/") < 0) @@ -728,6 +728,10 @@ from_client_kill_session(clicon_handle h, * @param[out] cbret Return xml value cligen buffer * @retval 0 OK * @retval -1 Error. Send error message back to client. + * NACM: If source running and target startup --> only exec permission + * else: + * - omit data nodes to which the client does not have read access + * - access denied if user lacks create/delete/update */ static int from_client_copy_config(clicon_handle h, @@ -1052,7 +1056,7 @@ from_client_msg(clicon_handle h, clicon_debug(1, "%s module:%s rpc:%s", __FUNCTION__, module, rpc); /* Pre-NACM access step */ xnacm = NULL; - if ((ret = nacm_access_h(h, username, &xnacm)) < 0) + if ((ret = nacm_access_pre(h, username, &xnacm)) < 0) goto done; if (ret == 0){ /* Do NACM validation */ /* NACM rpc operation exec validation */ diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index 19cc96d3..453e3e6c 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -323,6 +323,10 @@ candidate_commit(clicon_handle h, * @param[out] cbret Return xml value cligen buffer * @retval 0 OK. This may indicate both ok and err msg back to client * @retval -1 (Local) Error + * NACM: The server MUST determine the exact nodes in the running + * configuration datastore that are actually different and only check + * "create", "update", and "delete" access permissions for this set of + * nodes, which could be empty. */ int from_client_commit(clicon_handle h, @@ -368,6 +372,7 @@ from_client_commit(clicon_handle h, * @param[out] cbret Return xml value cligen buffer * @retval 0 OK. This may indicate both ok and err msg back to client * @retval -1 (Local) Error + * NACM: No datastore permissions are needed. */ int from_client_discard_changes(clicon_handle h, diff --git a/doc/FAQ.md b/doc/FAQ.md index 1677ad7b..ff0ed3a1 100644 --- a/doc/FAQ.md +++ b/doc/FAQ.md @@ -306,6 +306,7 @@ You may also add a default method in the configuration file: Yes. Systemd example files are provide for the backend and the restconf daemon as part of the [example](../example/systemd). + ## How can I add extra XML? There are two ways to add extra XML to running database after start. Note that this XML is not "committed" into running. @@ -474,6 +475,14 @@ To authenticate, the callback needs to return the value 1 and supply a username. See [../apps/example/example_restconf.c] example_restconf_credentials() for an example of HTTP basic auth. +## What about access control? + +Clixon has experimental support of the Network Configuration Access +Control Model defined in [RFC8341](https://tools.ietf.org/html/rfc8341) + +Incoming RPC and data node access points are supported with some +limitations. See the (README)(../README.md) for more information. + ## How do I write a CLI translator function? The CLI can perform variable translation. This is useful if you want to diff --git a/lib/clixon/clixon_nacm.h b/lib/clixon/clixon_nacm.h index f7a57318..4b016dd5 100644 --- a/lib/clixon/clixon_nacm.h +++ b/lib/clixon/clixon_nacm.h @@ -67,7 +67,7 @@ int nacm_rpc(char *rpc, char *module, char *username, cxobj *xnacm, cbuf *cbret) int nacm_datanode_read(cxobj *xt, cxobj **xvec, size_t xlen, char *username, cxobj *nacm_xtree); int nacm_datanode_write(cxobj *xt, cxobj *xr, enum nacm_access access, char *username, cxobj *xnacm, cbuf *cbret); -int nacm_access_h(clicon_handle h, char *username, cxobj **xnacmp); +int nacm_access_pre(clicon_handle h, char *username, cxobj **xnacmp); int nacm_access(char *mode, cxobj *xnacmin, char *username); #endif /* _CLIXON_NACM_H */ diff --git a/lib/src/clixon_nacm.c b/lib/src/clixon_nacm.c index f24a429c..60fa115b 100644 --- a/lib/src/clixon_nacm.c +++ b/lib/src/clixon_nacm.c @@ -101,23 +101,9 @@ match_access(char *access_operations, * @param[out] cbret Cligen buffer result. Set to an error msg if retval=0. * @retval -1 Error * @retval 0 Matching rule AND Not access and cbret set - * @retval 1 Matchung rule AND Access + * @retval 1 Matching rule AND Access * @retval 2 No matching rule Goto step 10 - * From RFC8341 3.4.4. Incoming RPC Message Validation - +---------+-----------------+---------------------+-----------------+ - | Method | Resource class | NETCONF operation | Access | - | | | | operation | - +---------+-----------------+---------------------+-----------------+ - | OPTIONS | all | none | none | - | HEAD | all | , | read | - | GET | all | , | read | - | POST | datastore, data | | create | - | POST | operation | specified operation | execute | - | PUT | data | | create, update | - | PUT | datastore | | update | - | PATCH | data, datastore | | update | - | DELETE | data | | delete | - + * @see RFC8341 3.4.4. Incoming RPC Message Validation 7.(cont) A rule matches if all of the following criteria are met: * The rule's "module-name" leaf is "*" or equals the name of the YANG module where the protocol operation is defined. @@ -133,44 +119,40 @@ match_access(char *access_operations, static int nacm_rule_rpc(char *rpc, char *module, - cxobj *xrule, - cbuf *cbret) + cxobj *xrule) { int retval = -1; char *module_rule; /* rule module name */ char *rpc_rule; char *access_operations; - char *action; - module_rule = xml_find_body(xrule, "module-name"); - rpc_rule = xml_find_body(xrule, "rpc-name"); - /* XXX access_operations can be a set of bits */ - access_operations = xml_find_body(xrule, "access-operations"); - action = xml_find_body(xrule, "action"); - clicon_debug(1, "%s: %s %s %s %s", __FUNCTION__, - module_rule, rpc_rule, access_operations, action); - if (module_rule && - (strcmp(module_rule,"*")==0 || strcmp(module_rule,module)==0)){ - if (match_access(access_operations, "exec", NULL)){ - if (rpc_rule==NULL || - strcmp(rpc_rule, "*")==0 || strcmp(rpc_rule, rpc)==0){ - /* Here is a matching rule */ - if (action && strcmp(action, "permit")==0){ - retval = 1; - goto done; - } - else{ - if (netconf_access_denied(cbret, "protocol", "access denied") < 0) - goto done; - retval = 0; - goto done; - } - } - } + /* 7a) The rule's "module-name" leaf is "*" or equals the name of + the YANG module where the protocol operation is defined. */ + if ((module_rule = xml_find_body(xrule, "module-name")) == NULL) + goto nomatch; + if (strcmp(module_rule,"*") && strcmp(module_rule,module)) + goto nomatch; + /* 7b) Either (1) the rule does not have a "rule-type" defined or + (2) the "rule-type" is "protocol-operation" and the + "rpc-name" is "*" or equals the name of the requested + protocol operation. */ + if ((rpc_rule = xml_find_body(xrule, "rpc-name")) == NULL){ + if (xml_find_body(xrule, "path") || xml_find_body(xrule, "notification-name")) + goto nomatch; } - retval = 2; /* no matching rule */ + if (rpc_rule && (strcmp(rpc_rule, "*") && strcmp(rpc_rule, rpc))) + goto nomatch; + /* 7c) The rule's "access-operations" leaf has the "exec" bit set or + has the special value "*". */ + access_operations = xml_find_body(xrule, "access-operations"); + if (!match_access(access_operations, "exec", NULL)) + goto nomatch; + retval = 1; done: return retval; + nomatch: + retval = 0; + goto done; } /*! Process nacm incoming RPC message validation steps @@ -202,10 +184,11 @@ nacm_rpc(char *rpc, size_t rlistlen; cxobj **rvec = NULL; /* rules */ size_t rlen; - int ret; int i, j; char *exec_default = NULL; char *gname; + char *action; + int match= 0; /* 3. If the requested operation is the NETCONF protocol operation, then the protocol operation is permitted. @@ -249,25 +232,30 @@ nacm_rpc(char *rpc, goto done; for (j=0; j or , then the protocol operation is denied. */ if (strcmp(rpc, "kill-session")==0 || strcmp(rpc, "delete-config")==0){ - if (netconf_access_denied(cbret, "protocol", "default deny") < 0) + if (netconf_access_denied(cbret, "application", "default deny") < 0) goto done; goto deny; } @@ -286,7 +274,7 @@ nacm_rpc(char *rpc, exec_default = xml_find_body(xnacm, "exec-default"); if (exec_default ==NULL || strcmp(exec_default, "permit")==0) goto permit; - if (netconf_access_denied(cbret, "protocol", "default deny") < 0) + if (netconf_access_denied(cbret, "application", "default deny") < 0) goto done; goto deny; permit: @@ -307,45 +295,31 @@ nacm_rpc(char *rpc, } /*--------------------------------------------------------------- - * Datanode/module read + * Datanode/module read and write */ -/*! We have a rule matching user group. Now match proper read operation and module - * @see RFC8341 3.4.5. Data Node Access Validation point (6) +/*! We have a rule matching user group. Now match proper write operation and module * @retval -1 Error * @retval 0 No Match * @retval 1 Match - * @see rule_data_write + * @see RFC8341 3.4.5. Data Node Access Validation point (6) */ static int -rule_data_read(cxobj *xrule, - cxobj *xr, - cxobj *xt) +nacm_rule_datanode(cxobj *xt, + cxobj *xr, + cxobj *xrule, + enum nacm_access access) { int retval = -1; - cxobj *xp; /* parent */ + char *path; char *access_operations; char *module_rule; /* rule module name */ yang_stmt *ys; yang_stmt *ymod; char *module; - char *path; cxobj *xpath; /* xpath match */ - - /* 6b) Either (1) the rule does not have a "rule-type" defined or - (2) the "rule-type" is "data-node" and the "path" matches the - requested data node, action node, or notification node. A - path is considered to match if the requested node is the node - specified by the path or is a descendant node of the path.*/ - if ((path = xml_find_body(xrule, "path")) == NULL){ - if (xml_find_body(xrule, "rpc-name") ||xml_find_body(xrule, "notification-name")) - goto nomatch; - } - /* 6c) For a "read" access operation, the rule's "access-operations" - leaf has the "read" bit set or has the special value "*" */ - access_operations = xml_find_body(xrule, "access-operations"); - if (!match_access(access_operations, "read", NULL)) - goto nomatch; + cxobj *xp; /* parent */ + /* 6a) The rule's "module-name" leaf is "*" or equals the name of * the YANG module where the requested data node is defined. */ if ((module_rule = xml_find_body(xrule, "module-name")) == NULL) @@ -358,7 +332,46 @@ rule_data_read(cxobj *xrule, if (strcmp(module, module_rule) != 0) goto nomatch; } - /* Here module is matched, now check for path if any */ + + /* 6b) Either (1) the rule does not have a "rule-type" defined or + (2) the "rule-type" is "data-node" and the "path" matches the + requested data node, action node, or notification node. A + path is considered to match if the requested node is the node + specified by the path or is a descendant node of the path.*/ + if ((path = xml_find_body(xrule, "path")) == NULL){ + if (xml_find_body(xrule, "rpc-name") ||xml_find_body(xrule, "notification-name")) + goto nomatch; + } + access_operations = xml_find_body(xrule, "access-operations"); + switch (access){ + case NACM_READ: + /* 6c) For a "read" access operation, the rule's "access-operations" + leaf has the "read" bit set or has the special value "*" */ + if (!match_access(access_operations, "read", NULL)) + goto nomatch; + break; + case NACM_CREATE: + /* 6d) For a "create" access operation, the rule's "access-operations" + leaf has the "create" bit set or has the special value "*". */ + if (!match_access(access_operations, "create", "write")) + goto nomatch; + break; + case NACM_DELETE: + /* 6e) For a "delete" access operation, the rule's "access-operations" + leaf has the "delete" bit set or has the special value "*". */ + if (!match_access(access_operations, "delete", "write")) + goto nomatch; + break; + case NACM_UPDATE: + /* 6f) For an "update" access operation, the rule's "access-operations" + leaf has the "update" bit set or has the special value "*". */ + if (!match_access(access_operations, "update", "write")) + goto nomatch; + break; + default: + break; + } + /* Here module is matched, now check for path if any NYI */ if (path){ if ((xpath = xpath_first(xt, "%s", path)) == NULL) goto nomatch; @@ -420,13 +433,13 @@ nacm_data_read_xr(cxobj *xt, continue; /* 6. For each rule-list entry found, process all rules, in order, until a rule that matches the requested access operation is - found. (see 6 sub rules in rule_data_read) + found. (see 6 sub rules in nacm_rule_datanode */ if (xpath_vec(rlist, "rule", &rvec, &rlen) < 0) goto done; for (j=0; jys_argument; - if (strcmp(module, module_rule) != 0) - goto nomatch; - } - /* Here module is matched, now check for path if any */ - if (path){ - if ((xpath = xpath_first(xt, "%s", path)) == NULL) - goto nomatch; - /* The requested node xr is the node specified by the path or is a - * descendant node of the path: - * xmatch is one of xvec[] or an ancestor of the xvec[] nodes. - */ - xp = xr; - do { - if (xpath == xp) - goto match; - } while ((xp = xml_parent(xp)) != NULL); - } - match: - retval = 1; - done: - return retval; - nomatch: - retval = 0; - goto done; -} /*! Make nacm datanode and module rule write access validation * The operations of NACM are: create, read, update, delete, exec @@ -790,17 +703,21 @@ nacm_datanode_write(cxobj *xt, goto done; /* 6. For each rule-list entry found, process all rules, in order, until a rule that matches the requested access operation is - found. (see 6 sub rules in nacm_match_rule2) + found. (see 6 sub rules in nacm_rule_data_write) */ for (j=0; j]]>]]>' '^protocolaccess-deniederrordefault deny]]>]]>$' +expecteof "$clixon_netconf -U guest -qf $cfg" 0 ']]>]]>' '^applicationaccess-deniederrordefault deny]]>]]>$' new2 "guest read element fail" -expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/clixon-example:translate=key42/value)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' +expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/clixon-example:translate=key42/value)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' new2 "guest read other module fail" -expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' +expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/nacm-example:x)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' new2 "guest read state fail" -expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' +expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' new2 "guest read top ok (part)" -expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' +expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' #------- RPC operation @@ -248,10 +248,10 @@ new "limit rpc netconf ok" expecteof "$clixon_netconf -U wilma -qf $cfg" 0 '0]]>]]>' '^042]]>]]>$' new2 "guest rpc fail" -expecteq "$(curl -u guest:bar -s -X POST http://localhost/restconf/operations/clixon-example:example -d '{"clixon-example:input":{"x":42}}' )" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "access denied"}}} ' +expecteq "$(curl -u guest:bar -s -X POST http://localhost/restconf/operations/clixon-example:example -d '{"clixon-example:input":{"x":42}}' )" '{"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]]>]]>' '^protocolaccess-deniederroraccess denied]]>]]>$' +expecteof "$clixon_netconf -U guest -qf $cfg" 0 '0]]>]]>' '^applicationaccess-deniederroraccess denied]]>]]>$' #------------------ Set read-default permit @@ -267,7 +267,7 @@ expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/nacm-exa ' new2 "guest read state fail" -expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' +expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/clixon-example:state)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' new "Kill restconf daemon" diff --git a/test/test_nacm_module_write.sh b/test/test_nacm_module_write.sh index 49f708e7..20ea209c 100755 --- a/test/test_nacm_module_write.sh +++ b/test/test_nacm_module_write.sh @@ -184,7 +184,7 @@ MSG="$RULES" new "update root list permit" expecteq "$(curl -u andy:bar -sS -H 'Content-Type: application/yang-data+xml' -X PUT http://localhost/restconf/data -d "$MSG")" '' -new "delete root list deny" +new2 "delete root list deny" expecteq "$(curl -u wilma:bar -sS -X DELETE http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' new "delete root permit" diff --git a/test/test_nacm_protocol.sh b/test/test_nacm_protocol.sh index 211ccad6..14f6ed61 100755 --- a/test/test_nacm_protocol.sh +++ b/test/test_nacm_protocol.sh @@ -171,20 +171,20 @@ expecteq "$(curl -u andy:bar -sS -X GET http://localhost/restconf/data/nacm-exam # Rule 1: deny-kill-session new "deny-kill-session: limited fail (netconf)" -expecteof "$clixon_netconf -qf $cfg -U wilma" 0 "44]]>]]>" "^protocolaccess-deniederroraccess denied]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -U wilma" 0 "44]]>]]>" "^applicationaccess-deniederroraccess denied]]>]]>$" new "deny-kill-session: guest fail (netconf)" -expecteof "$clixon_netconf -qf $cfg -U guest" 0 "44]]>]]>" "^protocolaccess-deniederroraccess denied]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -U guest" 0 "44]]>]]>" "^applicationaccess-deniederroraccess denied]]>]]>$" new "deny-kill-session: admin ok (netconf)" expecteof "$clixon_netconf -qf $cfg -U andy" 0 "44]]>]]>" "^]]>]]>$" # Rule 2: deny-delete-config new "deny-delete-config: limited fail (netconf)" -expecteof "$clixon_netconf -qf $cfg -U wilma" 0 "]]>]]>" "^protocolaccess-deniederroraccess denied]]>]]>$" +expecteof "$clixon_netconf -qf $cfg -U wilma" 0 "]]>]]>" "^applicationaccess-deniederroraccess denied]]>]]>$" new2 "deny-delete-config: guest fail (restconf)" -expecteq "$(curl -u guest:bar -sS -X DELETE http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' +expecteq "$(curl -u guest:bar -sS -X DELETE http://localhost/restconf/data)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' # In restconf delete-config is translated to edit-config which is permitted new "deny-delete-config: limited fail (restconf) ok" @@ -212,7 +212,7 @@ new "permit-edit-config: limited ok restconf" expecteq "$(curl -u wilma:bar -sS -X PUT -d '{"nacm-example:x": 2}' http://localhost/restconf/data/nacm-example:x)" '' new2 "permit-edit-config: guest fail restconf" -expecteq "$(curl -u guest:bar -sS -X PUT -d '{"nacm-example:x": 2}' http://localhost/restconf/data/nacm-example:x)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' +expecteq "$(curl -u guest:bar -sS -X PUT -d '{"nacm-example:x": 2}' http://localhost/restconf/data/nacm-example:x)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} ' new "Kill restconf daemon" sudo pkill -u www-data -f "/www-data/clixon_restconf"