NACM cleanup, uniform rule function, change of function names, etc.

This commit is contained in:
Olof hagsand 2019-02-02 11:35:50 +01:00
parent 8bf5cb0de5
commit 1e4022e73c
13 changed files with 180 additions and 247 deletions

View file

@ -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

View file

@ -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
=======

View file

@ -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 */

View file

@ -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,

View file

@ -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

View file

@ -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 */

View file

@ -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 | <get>, <get-config> | read |
| GET | all | <get>, <get-config> | read |
| POST | datastore, data | <edit-config> | create |
| POST | operation | specified operation | execute |
| PUT | data | <edit-config> | create, update |
| PUT | datastore | <copy-config> | update |
| PATCH | data, datastore | <edit-config> | update |
| DELETE | data | <edit-config> | 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 <close-session>
protocol operation, then the protocol operation is permitted.
@ -249,25 +232,30 @@ nacm_rpc(char *rpc,
goto done;
for (j=0; j<rlen; j++){
xrule = rvec[j];
/* -1 error, 0 deny, 1 permit, 2 continue */
if ((ret = nacm_rule_rpc(rpc, module, xrule, cbret)) < 0)
if ((match = nacm_rule_rpc(rpc, module, xrule)) < 0)
goto done;
switch(ret){
case 0: /* deny */
goto deny;
if (match)
break;
case 1: /* permit */
goto permit;
break;
case 2: /* no match, continue */
break;
}
}
if (match)
break;
if (rvec){
free(rvec);
rvec=NULL;
}
}
if (match){
if ((action = xml_find_body(xrule, "action")) == NULL)
goto step10;
if (strcmp(action, "deny")==0){
if (netconf_access_denied(cbret, "application", "access denied") < 0)
goto done;
goto deny;
}
else if (strcmp(action, "permit")==0)
goto permit;
}
step10:
/* 10. If the requested protocol operation is defined in a YANG module
advertised in the server capabilities and the "rpc" statement
@ -277,7 +265,7 @@ nacm_rpc(char *rpc,
<kill-session> or <delete-config>, 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; j<rlen; j++){ /* Loop through rules */
xrule = rvec[j];
if ((match = rule_data_read(xrule, xr, xt)) < 0)
if ((match = nacm_rule_datanode(xt, xr, xrule, NACM_READ)) < 0)
goto done;
if (match) /* xrule match */
break;
@ -615,106 +628,6 @@ nacm_datanode_read(cxobj *xt,
free(rlistvec);
return retval;
}
/*---------------------------------------------------------------
* Datanode/module write (=create, delete, update)
*/
/*! 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 RFC8341 3.4.5. Data Node Access Validation point (6)
* @see rule_data_read
*/
static int
rule_data_write(cxobj *xt,
cxobj *xr,
cxobj *xrule,
enum nacm_access access)
{
int retval = -1;
char *path;
char *access_operations;
char *module_rule; /* rule module name */
yang_stmt *ys;
yang_stmt *ymod;
char *module;
cxobj *xpath; /* xpath match */
cxobj *xp; /* parent */
/* 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 "*" */
/* 6d) For a "create" access operation, the rule's
"access-operations" leaf has the "create" bit set or has the
special value "*".
6e) For a "delete" access operation, the rule's
"access-operations" leaf has the "delete" bit set or has the
special value "*".
6f) For an "update" access operation, the rule's
"access-operations" leaf has the "update" bit set or has the
special value "*". */
access_operations = xml_find_body(xrule, "access-operations");
switch (access){
case NACM_CREATE:
if (!match_access(access_operations, "create", "write"))
goto nomatch;
break;
case NACM_UPDATE:
if (!match_access(access_operations, "update", "write"))
goto nomatch;
break;
case NACM_DELETE:
if (!match_access(access_operations, "delete", "write"))
goto nomatch;
break;
default:
break;
}
/* 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)
goto nomatch;
if (strcmp(module_rule,"*")!=0){
if ((ys = xml_spec(xr)) == NULL)
goto nomatch;
ymod = ys_module(ys);
module = ymod->ys_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<rlen; j++){ /* Loop through rules */
xrule = rvec[j];
if ((match = rule_data_write(xt, xr, xrule, access)) < 0)
if ((match = nacm_rule_datanode(xt, xr, xrule, access)) < 0)
goto done;
if (match) /* match */
break;
}
if (match)
break;
if (rvec){
free(rvec);
rvec = NULL;
}
}
if (match){
if ((action = xml_find_body(xrule, "action")) == NULL)
@ -934,7 +851,7 @@ nacm_access(char *mode,
* @retval 1 OK permitted. You do not need to do next NACM step
* @code
* cxobj *xnacm = NULL;
* if ((ret = nacm_access_h(h, username, &xnacm)) < 0)
* if ((ret = nacm_access_pre(h, username, &xnacm)) < 0)
* err;
* if (ret == 0){
* // Next step NACM processing
@ -943,11 +860,10 @@ nacm_access(char *mode,
* @endcode
* @see RFC8341 3.4 Access Control Enforcement Procedures
*/
int
nacm_access_h(clicon_handle h,
char *username,
cxobj **xnacmp)
nacm_access_pre(clicon_handle h,
char *username,
cxobj **xnacmp)
{
int retval = -1;
char *mode;

View file

@ -7,6 +7,9 @@ application. Assumes setup of http daemon as describe under apps/restonf
- site.sh Add your site-specific modifications here
- test_nacm.sh Auth tests using internal NACM
- test_nacm_ext.sh Auth tests using external NACM (separate file)
- test_nacm_protocol.sh Auth tests for incoming RPC:s
- test_nacm_module_read.sh Auth tests for data node read operations
- test_nacm_module_write.sh Auth tests for data node write operations
- test_cli.sh CLI tests
- test_netconf.sh Netconf tests
- test_restconf.sh Restconf tests

View file

@ -165,16 +165,16 @@ expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/nacm-exa
'
new2 "guest get nacm"
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": "access denied"}}} '
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": "access denied"}}} '
new "admin edit nacm"
expecteq "$(curl -u andy:bar -sS -X PUT -d '{"nacm-example:x": 1}' http://localhost/restconf/data/nacm-example:x)" ""
new2 "limited edit nacm"
expecteq "$(curl -u wilma: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 wilma: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"}}} '
new2 "guest edit nacm"
expecteq "$(curl -u guest:bar -sS -X PUT -d '{"nacm-example:x": 3}' http://localhost/restconf/data/nacm-example:x)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "access denied"}}} '
expecteq "$(curl -u guest:bar -sS -X PUT -d '{"nacm-example:x": 3}' http://localhost/restconf/data/nacm-example:x)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "access denied"}}} '
new "Kill restconf daemon"
sudo pkill -u www-data -f "/www-data/clixon_restconf"

View file

@ -177,16 +177,16 @@ expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data/nacm-exa
'
new2 "guest get nacm"
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": "access denied"}}} '
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": "access denied"}}} '
new "admin edit nacm"
expecteq "$(curl -u andy:bar -sS -X PUT -d '{"nacm-example:x": 1}' http://localhost/restconf/data/nacm-example:x)" ""
new2 "limited edit nacm"
expecteq "$(curl -u wilma:bar -sS -X PUT -d '{"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 wilma:bar -sS -X PUT -d '{"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"}}} '
new2 "guest edit nacm"
expecteq "$(curl -u guest:bar -sS -X PUT -d '{"x": 3}' http://localhost/restconf/data/nacm-example:x)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "access-denied","error-severity": "error","error-message": "access denied"}}} '
expecteq "$(curl -u guest:bar -sS -X PUT -d '{"x": 3}' http://localhost/restconf/data/nacm-example:x)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "access denied"}}} '
new "cli show conf as admin"
expectfn "$clixon_cli -1 -U andy -l o -f $cfg show conf" 0 "^x 1;$"

View file

@ -214,22 +214,22 @@ expecteq "$(curl -u wilma:bar -sS -X GET http://localhost/restconf/data)" '{"dat
#user:guest
new2 "guest read fail"
expecteq "$(curl -u guest:bar -sS -X GET http://localhost/restconf/data/clixon-example:translate)" '{"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)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "access-denied","error-severity": "error","error-message": "default deny"}}} '
new2 "guest read netconf fail"
expecteof "$clixon_netconf -U guest -qf $cfg" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/translate"/></get-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>default deny</error-message></rpc-error></rpc-reply>]]>]]>$'
expecteof "$clixon_netconf -U guest -qf $cfg" 0 '<rpc><get-config><source><candidate/></source><filter type="xpath" select="/translate"/></get-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>default deny</error-message></rpc-error></rpc-reply>]]>]]>$'
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 '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><example xmlns="urn:example:clixon"><x>0</x></example></rpc>]]>]]>' '^<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><x xmlns="urn:example:clixon">0</x><y xmlns="urn:example:clixon">42</y></rpc-reply>]]>]]>$'
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 '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><example xmlns="urn:example:clixon"><x>0</x></example></rpc>]]>]]>' '^<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><rpc-error><error-type>protocol</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>access denied</error-message></rpc-error></rpc-reply>]]>]]>$'
expecteof "$clixon_netconf -U guest -qf $cfg" 0 '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><example xmlns="urn:example:clixon"><x>0</x></example></rpc>]]>]]>' '^<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><rpc-error><error-type>application</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>access denied</error-message></rpc-error></rpc-reply>]]>]]>$'
#------------------ 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"

View file

@ -184,7 +184,7 @@ MSG="<data>$RULES</data>"
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"

View file

@ -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 "<rpc><kill-session><session-id>44</session-id></kill-session></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>access denied</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -U wilma" 0 "<rpc><kill-session><session-id>44</session-id></kill-session></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>access denied</error-message></rpc-error></rpc-reply>]]>]]>$"
new "deny-kill-session: guest fail (netconf)"
expecteof "$clixon_netconf -qf $cfg -U guest" 0 "<rpc><kill-session><session-id>44</session-id></kill-session></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>access denied</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -U guest" 0 "<rpc><kill-session><session-id>44</session-id></kill-session></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>access denied</error-message></rpc-error></rpc-reply>]]>]]>$"
new "deny-kill-session: admin ok (netconf)"
expecteof "$clixon_netconf -qf $cfg -U andy" 0 "<rpc><kill-session><session-id>44</session-id></kill-session></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
# Rule 2: deny-delete-config
new "deny-delete-config: limited fail (netconf)"
expecteof "$clixon_netconf -qf $cfg -U wilma" 0 "<rpc><delete-config><target><startup/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-type>protocol</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>access denied</error-message></rpc-error></rpc-reply>]]>]]>$"
expecteof "$clixon_netconf -qf $cfg -U wilma" 0 "<rpc><delete-config><target><startup/></target></delete-config></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>access-denied</error-tag><error-severity>error</error-severity><error-message>access denied</error-message></rpc-error></rpc-reply>]]>]]>$"
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"