NACM write path delete works as well
This commit is contained in:
parent
1dff0e681b
commit
5be5b02a84
7 changed files with 86 additions and 64 deletions
|
|
@ -27,7 +27,7 @@ Expected: May 2020
|
||||||
### Major New features
|
### Major New features
|
||||||
|
|
||||||
* NACM RFC8341 datanode read and write paths
|
* NACM RFC8341 datanode read and write paths
|
||||||
* This completes the NACM RPC and Data node access checks (notification still remains)
|
* This completes the NACM RPC and Data node access checks (only remaining NACM access point is notification)
|
||||||
|
|
||||||
### API changes on existing protocol/config features (You may have have to change how you use Clixon)
|
### API changes on existing protocol/config features (You may have have to change how you use Clixon)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ enum nacm_access{
|
||||||
int nacm_rpc(char *rpc, char *module, char *username, cxobj *xnacm, cbuf *cbret);
|
int nacm_rpc(char *rpc, char *module, char *username, cxobj *xnacm, cbuf *cbret);
|
||||||
int nacm_datanode_read(clicon_handle h, cxobj *xt, cxobj **xvec, size_t xlen, char *username,
|
int nacm_datanode_read(clicon_handle h, cxobj *xt, cxobj **xvec, size_t xlen, char *username,
|
||||||
cxobj *nacm_xtree);
|
cxobj *nacm_xtree);
|
||||||
int nacm_datanode_write(clicon_handle h, cxobj *xt, cxobj *xr, enum nacm_access access,
|
int nacm_datanode_write(clicon_handle h, cxobj *xr, cxobj *xt,
|
||||||
|
enum nacm_access access,
|
||||||
char *username, cxobj *xnacm, cbuf *cbret);
|
char *username, cxobj *xnacm, cbuf *cbret);
|
||||||
int nacm_access_pre(clicon_handle h, char *username, cxobj **xnacmp);
|
int nacm_access_pre(clicon_handle h, char *username, cxobj **xnacmp);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,7 @@ int xml_apply(cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg
|
||||||
int xml_apply0(cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg);
|
int xml_apply0(cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg);
|
||||||
int xml_apply_ancestor(cxobj *xn, xml_applyfn_t fn, void *arg);
|
int xml_apply_ancestor(cxobj *xn, xml_applyfn_t fn, void *arg);
|
||||||
int xml_isancestor(cxobj *x, cxobj *xp);
|
int xml_isancestor(cxobj *x, cxobj *xp);
|
||||||
|
cxobj *xml_root(cxobj *xn);
|
||||||
|
|
||||||
int xml_operation(char *opstr, enum operation_type *op);
|
int xml_operation(char *opstr, enum operation_type *op);
|
||||||
char *xml_operation2str(enum operation_type op);
|
char *xml_operation2str(enum operation_type op);
|
||||||
|
|
|
||||||
|
|
@ -227,10 +227,11 @@ check_body_namespace(cxobj *x0,
|
||||||
static int
|
static int
|
||||||
text_modify(clicon_handle h,
|
text_modify(clicon_handle h,
|
||||||
cxobj *x0,
|
cxobj *x0,
|
||||||
yang_stmt *y0,
|
|
||||||
cxobj *x0p,
|
cxobj *x0p,
|
||||||
|
cxobj *x0t,
|
||||||
cxobj *x1,
|
cxobj *x1,
|
||||||
cxobj *x1t,
|
cxobj *x1t,
|
||||||
|
yang_stmt *y0,
|
||||||
enum operation_type op,
|
enum operation_type op,
|
||||||
char *username,
|
char *username,
|
||||||
cxobj *xnacm,
|
cxobj *xnacm,
|
||||||
|
|
@ -319,7 +320,7 @@ text_modify(clicon_handle h,
|
||||||
* of ordered-by user and (changed) insert attribute.
|
* of ordered-by user and (changed) insert attribute.
|
||||||
*/
|
*/
|
||||||
if (!permit && xnacm){
|
if (!permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x1, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_datanode_write(h, x1, x1t, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -336,7 +337,7 @@ text_modify(clicon_handle h,
|
||||||
case OP_NONE: /* fall thru */
|
case OP_NONE: /* fall thru */
|
||||||
if (x0==NULL){
|
if (x0==NULL){
|
||||||
if ((op != OP_NONE) && !permit && xnacm){
|
if ((op != OP_NONE) && !permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x1, NACM_CREATE, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_datanode_write(h, x1, x1t, NACM_CREATE, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -403,7 +404,7 @@ text_modify(clicon_handle h,
|
||||||
x0bstr = xml_value(x0b);
|
x0bstr = xml_value(x0b);
|
||||||
if (x0bstr==NULL || strcmp(x0bstr, x1bstr)){
|
if (x0bstr==NULL || strcmp(x0bstr, x1bstr)){
|
||||||
if ((op != OP_NONE) && !permit && xnacm){
|
if ((op != OP_NONE) && !permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x1,
|
if ((ret = nacm_datanode_write(h, x1, x1t,
|
||||||
x0bstr==NULL?NACM_CREATE:NACM_UPDATE,
|
x0bstr==NULL?NACM_CREATE:NACM_UPDATE,
|
||||||
username, xnacm, cbret)) < 0)
|
username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -429,7 +430,7 @@ text_modify(clicon_handle h,
|
||||||
case OP_REMOVE: /* fall thru */
|
case OP_REMOVE: /* fall thru */
|
||||||
if (x0){
|
if (x0){
|
||||||
if ((op != OP_NONE) && !permit && xnacm){
|
if ((op != OP_NONE) && !permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x0, NACM_DELETE, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_datanode_write(h, x0, x0t, NACM_DELETE, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -491,7 +492,7 @@ text_modify(clicon_handle h,
|
||||||
* of ordered-by user and (changed) insert attribute.
|
* of ordered-by user and (changed) insert attribute.
|
||||||
*/
|
*/
|
||||||
if (!permit && xnacm){
|
if (!permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x1, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_datanode_write(h, x1, x1t, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -517,7 +518,7 @@ text_modify(clicon_handle h,
|
||||||
if (op == OP_NONE)
|
if (op == OP_NONE)
|
||||||
break;
|
break;
|
||||||
if (op==OP_MERGE && !permit && xnacm){
|
if (op==OP_MERGE && !permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x0, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_datanode_write(h, x1, x1t, x0?NACM_UPDATE:NACM_CREATE, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -534,7 +535,7 @@ text_modify(clicon_handle h,
|
||||||
} /* anyxml, anydata */
|
} /* anyxml, anydata */
|
||||||
if (x0==NULL){
|
if (x0==NULL){
|
||||||
if (op==OP_MERGE && !permit && xnacm){
|
if (op==OP_MERGE && !permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x1, NACM_CREATE, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_datanode_write(h, x1, x1t, NACM_CREATE, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -605,7 +606,8 @@ text_modify(clicon_handle h,
|
||||||
x1cname = xml_name(x1c);
|
x1cname = xml_name(x1c);
|
||||||
x0c = x0vec[i++];
|
x0c = x0vec[i++];
|
||||||
yc = yang_find_datanode(y0, x1cname);
|
yc = yang_find_datanode(y0, x1cname);
|
||||||
if ((ret = text_modify(h, x0c, yc, x0, x1c, x1t, op,
|
if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t,
|
||||||
|
yc, op,
|
||||||
username, xnacm, permit, cbret)) < 0)
|
username, xnacm, permit, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* If xml return - ie netconf error xml tree, then stop and return OK */
|
/* If xml return - ie netconf error xml tree, then stop and return OK */
|
||||||
|
|
@ -626,7 +628,7 @@ text_modify(clicon_handle h,
|
||||||
case OP_REMOVE: /* fall thru */
|
case OP_REMOVE: /* fall thru */
|
||||||
if (x0){
|
if (x0){
|
||||||
if (!permit && xnacm){
|
if (!permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x0, NACM_DELETE, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_datanode_write(h, x0, x0t, NACM_DELETE, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -673,6 +675,7 @@ text_modify(clicon_handle h,
|
||||||
static int
|
static int
|
||||||
text_modify_top(clicon_handle h,
|
text_modify_top(clicon_handle h,
|
||||||
cxobj *x0,
|
cxobj *x0,
|
||||||
|
cxobj *x0t,
|
||||||
cxobj *x1,
|
cxobj *x1,
|
||||||
cxobj *x1t,
|
cxobj *x1t,
|
||||||
yang_stmt *yspec,
|
yang_stmt *yspec,
|
||||||
|
|
@ -709,7 +712,7 @@ text_modify_top(clicon_handle h,
|
||||||
case OP_REMOVE:
|
case OP_REMOVE:
|
||||||
case OP_REPLACE:
|
case OP_REPLACE:
|
||||||
if (!permit && xnacm){
|
if (!permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x0, NACM_DELETE, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_datanode_write(h, x0, x0t, NACM_DELETE, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -743,7 +746,7 @@ text_modify_top(clicon_handle h,
|
||||||
/* Special case top-level replace */
|
/* Special case top-level replace */
|
||||||
else if (op == OP_REPLACE || op == OP_DELETE){
|
else if (op == OP_REPLACE || op == OP_DELETE){
|
||||||
if (!permit && xnacm){
|
if (!permit && xnacm){
|
||||||
if ((ret = nacm_datanode_write(h, x1t, x1, NACM_UPDATE, username, xnacm, cbret)) < 0)
|
if ((ret = nacm_datanode_write(h, x1, x1t, NACM_UPDATE, username, xnacm, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -777,7 +780,8 @@ text_modify_top(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
x0c = NULL;
|
x0c = NULL;
|
||||||
}
|
}
|
||||||
if ((ret = text_modify(h, x0c, yc, x0, x1c, x1t, op,
|
if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t,
|
||||||
|
yc, op,
|
||||||
username, xnacm, permit, cbret)) < 0)
|
username, xnacm, permit, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* If xml return - ie netconf error xml tree, then stop and return OK */
|
/* If xml return - ie netconf error xml tree, then stop and return OK */
|
||||||
|
|
@ -921,7 +925,7 @@ xmldb_put(clicon_handle h,
|
||||||
* Modify base tree x with modification x1. This is where the
|
* Modify base tree x with modification x1. This is where the
|
||||||
* new tree is made.
|
* new tree is made.
|
||||||
*/
|
*/
|
||||||
if ((ret = text_modify_top(h, x0, x1, x1, yspec, op, username, xnacm, permit, cbret)) < 0)
|
if ((ret = text_modify_top(h, x0, x0, x1, x1, yspec, op, username, xnacm, permit, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* If xml return - ie netconf error xml tree, then stop and return OK */
|
/* If xml return - ie netconf error xml tree, then stop and return OK */
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
|
|
|
||||||
|
|
@ -462,9 +462,9 @@ nacm_datanode_prepare(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! Match specific rule to specific requested node
|
/*! Match specific rule to specific requested node
|
||||||
* @param[in] xt XML root tree with "config" label
|
|
||||||
* @param[in] xn XML node (requested node)
|
* @param[in] xn XML node (requested node)
|
||||||
* @param[in] xrule NACM rule
|
* @param[in] xrule NACM rule
|
||||||
|
* @param[in] xp Xpath match
|
||||||
* @param[in] yspec YANG spec
|
* @param[in] yspec YANG spec
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 OK and rule does not match
|
* @retval 0 OK and rule does not match
|
||||||
|
|
@ -473,43 +473,15 @@ nacm_datanode_prepare(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
nacm_data_write_xrule_xml(cxobj *xn,
|
nacm_data_write_xrule_xml(cxobj *xn,
|
||||||
enum nacm_access access,
|
|
||||||
cxobj *xrule,
|
cxobj *xrule,
|
||||||
cxobj *xp,
|
cxobj *xp,
|
||||||
yang_stmt *yspec)
|
yang_stmt *yspec)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *pathobj;
|
|
||||||
yang_stmt *ymod;
|
yang_stmt *ymod;
|
||||||
char *module_pattern; /* rule module name */
|
char *module_pattern; /* rule module name */
|
||||||
char *access_operations;
|
|
||||||
char *action;
|
char *action;
|
||||||
|
|
||||||
access_operations = xml_find_body(xrule, "access-operations");
|
|
||||||
switch (access){
|
|
||||||
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:
|
|
||||||
clicon_err(OE_XML, EINVAL, "Access %d unupported (shouldnt happen)", access);
|
|
||||||
goto done;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((module_pattern = xml_find_body(xrule, "module-name")) == NULL)
|
if ((module_pattern = xml_find_body(xrule, "module-name")) == NULL)
|
||||||
goto nomatch;
|
goto nomatch;
|
||||||
/* 6a) The rule's "module-name" leaf is "*" or equals the name of
|
/* 6a) The rule's "module-name" leaf is "*" or equals the name of
|
||||||
|
|
@ -525,7 +497,7 @@ nacm_data_write_xrule_xml(cxobj *xn,
|
||||||
/* 6b) Either (1) the rule does not have a "rule-type" defined or
|
/* 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
|
(2) the "rule-type" is "data-node" and the "path" matches the
|
||||||
Requested data node, action node, or notification node. */
|
Requested data node, action node, or notification node. */
|
||||||
if ((pathobj = xml_find_type(xrule, NULL, "path", CX_ELMNT)) == NULL){
|
if (xml_find_type(xrule, NULL, "path", CX_ELMNT) == NULL){
|
||||||
if (strcmp(action, "deny")==0)
|
if (strcmp(action, "deny")==0)
|
||||||
goto deny;
|
goto deny;
|
||||||
goto permit;
|
goto permit;
|
||||||
|
|
@ -549,7 +521,6 @@ nacm_data_write_xrule_xml(cxobj *xn,
|
||||||
|
|
||||||
/*! Recursive check for NACM write rules among all XML nodes
|
/*! Recursive check for NACM write rules among all XML nodes
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] access NACM access right
|
|
||||||
* @param[in] xn XML node (requested node)
|
* @param[in] xn XML node (requested node)
|
||||||
* @param[in] rulevec Precomputed rules that apply to this user group
|
* @param[in] rulevec Precomputed rules that apply to this user group
|
||||||
* @param[in] xpathvec Precomputed xpath results that apply to this XML tree
|
* @param[in] xpathvec Precomputed xpath results that apply to this XML tree
|
||||||
|
|
@ -567,7 +538,6 @@ nacm_data_write_xrule_xml(cxobj *xn,
|
||||||
static int
|
static int
|
||||||
nacm_datanode_write_recurse(clicon_handle h,
|
nacm_datanode_write_recurse(clicon_handle h,
|
||||||
cxobj *xn,
|
cxobj *xn,
|
||||||
enum nacm_access access,
|
|
||||||
clixon_xvec *rulevec,
|
clixon_xvec *rulevec,
|
||||||
clixon_xvec *xpathvec,
|
clixon_xvec *xpathvec,
|
||||||
int defpermit,
|
int defpermit,
|
||||||
|
|
@ -580,7 +550,7 @@ nacm_datanode_write_recurse(clicon_handle h,
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
for (i=0; i<clixon_xvec_len(rulevec); i++){ /* Loop through rule list */
|
for (i=0; i<clixon_xvec_len(rulevec); i++){ /* Loop through rule list */
|
||||||
if ((ret = nacm_data_write_xrule_xml(xn, access,
|
if ((ret = nacm_data_write_xrule_xml(xn,
|
||||||
clixon_xvec_i(rulevec, i),
|
clixon_xvec_i(rulevec, i),
|
||||||
clixon_xvec_i(xpathvec, i),
|
clixon_xvec_i(xpathvec, i),
|
||||||
yspec)) < 0)
|
yspec)) < 0)
|
||||||
|
|
@ -605,7 +575,7 @@ nacm_datanode_write_recurse(clicon_handle h,
|
||||||
/* If node should be purged, dont recurse and defer removal to caller */
|
/* If node should be purged, dont recurse and defer removal to caller */
|
||||||
x = NULL; /* Recursively check XML */
|
x = NULL; /* Recursively check XML */
|
||||||
while ((x = xml_child_each(xn, x, CX_ELMNT)) != NULL) {
|
while ((x = xml_child_each(xn, x, CX_ELMNT)) != NULL) {
|
||||||
if ((ret = nacm_datanode_write_recurse(h, x, access,
|
if ((ret = nacm_datanode_write_recurse(h, x,
|
||||||
rulevec, xpathvec,
|
rulevec, xpathvec,
|
||||||
defpermit, yspec, cbret)) < 0)
|
defpermit, yspec, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -624,8 +594,8 @@ nacm_datanode_write_recurse(clicon_handle h,
|
||||||
* The operations of NACM are: create, read, update, delete, exec
|
* The operations of NACM are: create, read, update, delete, exec
|
||||||
* where write is short-hand for create+delete+update
|
* where write is short-hand for create+delete+update
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] xt XML root tree with "config" label.
|
* @param[in] xreq XML requestor node (part of xt) for delete it is existing, for others it is new
|
||||||
* @param[in] xreq XML requestor node (part of xt)
|
* @param[in] xt XML request root tree with "config" label at top.
|
||||||
* @param[in] op NACM access of xreq
|
* @param[in] op NACM access of xreq
|
||||||
* @param[in] username User making access
|
* @param[in] username User making access
|
||||||
* @param[in] xnacm NACM xml tree
|
* @param[in] xnacm NACM xml tree
|
||||||
|
|
@ -639,8 +609,8 @@ nacm_datanode_write_recurse(clicon_handle h,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
nacm_datanode_write(clicon_handle h,
|
nacm_datanode_write(clicon_handle h,
|
||||||
cxobj *xt,
|
|
||||||
cxobj *xreq,
|
cxobj *xreq,
|
||||||
|
cxobj *xt,
|
||||||
enum nacm_access access,
|
enum nacm_access access,
|
||||||
char *username,
|
char *username,
|
||||||
cxobj *xnacm,
|
cxobj *xnacm,
|
||||||
|
|
@ -698,7 +668,7 @@ nacm_datanode_write(clicon_handle h,
|
||||||
rulevec, xpathvec) < 0)
|
rulevec, xpathvec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Then recursivelyy traverse all requested nodes */
|
/* Then recursivelyy traverse all requested nodes */
|
||||||
if ((ret = nacm_datanode_write_recurse(h, xreq, access,
|
if ((ret = nacm_datanode_write_recurse(h, xreq,
|
||||||
rulevec, xpathvec,
|
rulevec, xpathvec,
|
||||||
strcmp(write_default, "deny"),
|
strcmp(write_default, "deny"),
|
||||||
clicon_dbspec_yang(h),
|
clicon_dbspec_yang(h),
|
||||||
|
|
@ -798,7 +768,6 @@ nacm_data_read_xrule_xml(cxobj *xn,
|
||||||
yang_stmt *yspec)
|
yang_stmt *yspec)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj *pathobj;
|
|
||||||
yang_stmt *ymod;
|
yang_stmt *ymod;
|
||||||
char *module_pattern; /* rule module name */
|
char *module_pattern; /* rule module name */
|
||||||
|
|
||||||
|
|
@ -816,7 +785,7 @@ nacm_data_read_xrule_xml(cxobj *xn,
|
||||||
/* 6b) Either (1) the rule does not have a "rule-type" defined or
|
/* 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
|
(2) the "rule-type" is "data-node" and the "path" matches the
|
||||||
requested data node, action node, or notification node. */
|
requested data node, action node, or notification node. */
|
||||||
if ((pathobj = xml_find_type(xrule, NULL, "path", CX_ELMNT)) == NULL){
|
if (xml_find_type(xrule, NULL, "path", CX_ELMNT) == NULL){
|
||||||
if (nacm_data_read_action(xrule, xn) < 0)
|
if (nacm_data_read_action(xrule, xn) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto match;
|
goto match;
|
||||||
|
|
|
||||||
|
|
@ -2158,6 +2158,22 @@ xml_isancestor(cxobj *x,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Get ultimate root ancestor of an xml-node: top-level node without parent
|
||||||
|
* @param[in] xn XML node
|
||||||
|
* @retval xr XML root node (can be xn)
|
||||||
|
*/
|
||||||
|
cxobj *
|
||||||
|
xml_root(cxobj *xn)
|
||||||
|
{
|
||||||
|
cxobj *xp = NULL;
|
||||||
|
cxobj *x = NULL;
|
||||||
|
|
||||||
|
x = xn;
|
||||||
|
while ((xp = xml_parent(x)) != NULL)
|
||||||
|
x = xp;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Map xml operation from string to enumeration
|
/*! Map xml operation from string to enumeration
|
||||||
* @param[in] opstr String, eg "merge"
|
* @param[in] opstr String, eg "merge"
|
||||||
* @param[out] op Enumeration, eg OP_MERGE
|
* @param[out] op Enumeration, eg OP_MERGE
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
# 2. guest cannot read /nacm
|
# 2. guest cannot read /nacm
|
||||||
# 3. limited can read and set /config-parameters
|
# 3. limited can read and set /config-parameters
|
||||||
# 4. guest cannot set /config-parametesr
|
# 4. guest cannot set /config-parametesr
|
||||||
# 5. guest|limit cannot POST dummy interface
|
# 5. limit can read and update but not create or delete dummy interface
|
||||||
# 6. admin can POST dummy interface
|
# 6. admin can POST dummy interface
|
||||||
# 7. guest|limit can read and PUT dummy interface
|
# 7. guest|limit can read and PUT dummy interface
|
||||||
# 8. guest|limit cannot DELETE dummy interface
|
# 8. guest|limit cannot DELETE dummy interface
|
||||||
|
|
@ -104,7 +104,7 @@ module itf{
|
||||||
container interfaces{
|
container interfaces{
|
||||||
list interface{
|
list interface{
|
||||||
key name;
|
key name;
|
||||||
leaf key{
|
leaf name{
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
leaf value{
|
leaf value{
|
||||||
|
|
@ -268,18 +268,49 @@ expectpart "$(curl -u guest:bar -siS -X GET http://localhost/restconf/data/ietf-
|
||||||
new "3. limited can read config-parameters"
|
new "3. limited can read config-parameters"
|
||||||
expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/nacm-example:acme-netconf/config-parameters)" 0 'HTTP/1.1 200 OK' '{"nacm-example:config-parameters":{"parameter":\[{"name":"a","value":"72"}\]}}'
|
expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/nacm-example:acme-netconf/config-parameters)" 0 'HTTP/1.1 200 OK' '{"nacm-example:config-parameters":{"parameter":\[{"name":"a","value":"72"}\]}}'
|
||||||
|
|
||||||
|
|
||||||
new "3. limited can set config-parameters"
|
new "3. limited can set config-parameters"
|
||||||
expectpart "$(curl -u wilma:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/nacm-example:acme-netconf/config-parameters/parameter=a -d '{"nacm-example:parameter":[{"name":"a","value":"93"}]}')" 0 'HTTP/1.1 204 No Content'
|
expectpart "$(curl -u wilma:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/nacm-example:acme-netconf/config-parameters/parameter=a -d '{"nacm-example:parameter":[{"name":"a","value":"93"}]}')" 0 'HTTP/1.1 204 No Content'
|
||||||
|
|
||||||
new "4. guest cannot set /config-parameter"
|
new "4. guest cannot set /config-parameter"
|
||||||
expectpart "$(curl -u guest:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/nacm-example:acme-netconf/config-parameters/parameter=a -d '{"nacm-example:parameter":[{"name":"a","value":"93"}]}')" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}'
|
expectpart "$(curl -u guest:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/nacm-example:acme-netconf/config-parameters/parameter=a -d '{"nacm-example:parameter":[{"name":"a","value":"93"}]}')" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}'
|
||||||
|
|
||||||
# 5. guest|limit cannot POST dummy interface
|
# 5. limit can read and update but not create or delete dummy interface
|
||||||
# 6. admin can POST dummy interface
|
|
||||||
# 7. guest|limit can read and PUT dummy interface
|
new "5a. limit cannot create dummy interface"
|
||||||
# 8. guest|limit cannot DELETE dummy interface
|
expectpart "$(curl -u wilma:bar -siS -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/itf:interfaces -d '{"itf:interface":[{"name":"dummy","value":"93"}]}')" 0 'HTTP/1.1 403 Forbidden' '{"ietf-restconf:errors":{"error":{"error-type":"application","error-tag":"access-denied","error-severity":"error","error-message":"default deny"}}}'
|
||||||
# 9. admin can DELETE dummy interface
|
|
||||||
|
new "5b. admin can create dummy interface"
|
||||||
|
expectpart "$(curl -u andy:bar -siS -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/itf:interfaces -d '{"itf:interface":[{"name":"dummy","value":"93"}]}')" 0 'HTTP/1.1 201 Created'
|
||||||
|
|
||||||
|
new "5b. admin can create other interface x as reference"
|
||||||
|
expectpart "$(curl -u andy:bar -siS -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/itf:interfaces -d '{"itf:interface":[{"name":"x","value":"200"}]}')" 0 'HTTP/1.1 201 Created'
|
||||||
|
|
||||||
|
new "5c. limit can read dummy interface"
|
||||||
|
expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/itf:interfaces/interface=dummy)" 0 'HTTP/1.1 200 OK' '{"itf:interface":\[{"name":"dummy","value":"93"}\]}'
|
||||||
|
|
||||||
|
new "5c. limit can read other interface"
|
||||||
|
expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/itf:interfaces/interface=x)" 0 'HTTP/1.1 200 OK' '{"itf:interface":\[{"name":"x","value":"200"}\]}'
|
||||||
|
|
||||||
|
new "5d. limit can update dummy interface"
|
||||||
|
expectpart "$(curl -u wilma:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/itf:interfaces/interface=dummy -d '{"itf:interface":[{"name":"dummy","value":"42"}]}')" 0 'HTTP/1.1 204 No Content'
|
||||||
|
|
||||||
|
new "5d. admin can update dummy interface"
|
||||||
|
expectpart "$(curl -u andy:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/itf:interfaces/interface=dummy -d '{"itf:interface":[{"name":"dummy","value":"17"}]}')" 0 'HTTP/1.1 204 No Content'
|
||||||
|
|
||||||
|
new "5d. limit can not update other interface"
|
||||||
|
expectpart "$(curl -u wilma:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/itf:interfaces/interface=x -d '{"itf:interface":[{"name":"x","value":"42"}]}')" 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 "5d. admin can update other interface"
|
||||||
|
expectpart "$(curl -u andy:bar -siS -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/itf:interfaces/interface=x -d '{"itf:interface":[{"name":"x","value":"42"}]}')" 0 'HTTP/1.1 204 No Content'
|
||||||
|
|
||||||
|
new "5d. limit can read dummy interface (again)"
|
||||||
|
expectpart "$(curl -u wilma:bar -siS -X GET http://localhost/restconf/data/itf:interfaces/interface=dummy)" 0 'HTTP/1.1 200 OK' '{"itf:interface":\[{"name":"dummy","value":"17"}\]}'
|
||||||
|
|
||||||
|
new "5e. limit can not delete dummy interface"
|
||||||
|
expectpart "$(curl -u wilma:bar -siS -X DELETE http://localhost/restconf/data/itf:interfaces/interface=dummy)" 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 "5e. admin can delete dummy interface"
|
||||||
|
expectpart "$(curl -u andy:bar -siS -X DELETE http://localhost/restconf/data/itf:interfaces/interface=dummy)" 0 'HTTP/1.1 204 No Content'
|
||||||
|
|
||||||
if [ $RC -ne 0 ]; then
|
if [ $RC -ne 0 ]; then
|
||||||
new "Kill restconf daemon"
|
new "Kill restconf daemon"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue