When I added a default statement for the data node such as a leaf in yang model. if I loaded configuration from a file which didn’t set a value for that node, I was required to have write permission on that node. Otherwise CLI returned the error “access denied”.
When no default statement for that data node, even without write permission on that node, I was still able to load configuration from the same file.
Now I am curious how the default statement influences the behavior of load command in CLI. Could you help me with asking the question? Thanks.
Which ConfD version are you using? If you can provide a YANG snippet and NACM rules that can be used to reproduce the issue, that would help pinpoint the issue.
The CLI console of reproduction on native ConfD is shown as below.
node# show running-config | display xml | save file.xml
node# config
Entering configuration mode terminal
node(config)# load override file.xml
Loading.
Error: access denied
When CLI returned the error “access denied”, I found the below logs.
<DEBUG> 8-Jul-2022::06:09:47.887 node-150-132-197-18 confd[<0.337.0>]: devel-aaa User: admin[admin] rejected data access path /new:new/int op read due to no rule matched and /nacm/read-default is 'deny'
<DEBUG> 8-Jul-2022::06:09:47.887 node-150-132-197-18 confd[<0.337.0>]: devel-aaa User: admin[admin] rejected data access path /new:new/int op read due to no rule matched and /nacm/read-default is 'deny'
<DEBUG> 8-Jul-2022::06:09:59.895 node-150-132-197-18 confd[<0.376.0>]: devel-aaa User: admin[admin] rejected data access path /new:new op write due to no rule matched and /nacm/write-default is 'deny'
With the ConfD 7.8.3, 7.7.6 etc. releases sometime end of August I notice that there will be a correction to the behavior you describe:
The CLI command ‘load override file.xml’ would fail if the user didn’t have (NACM) delete access to the whole configuration. Now only the part of the configuration where the user has delete access will be attempted to be deleted, and the rest will be ignored.
I added the delete access for that model new and tested on ConfD 7.7.3 again, that error didn’t occur no longer. But I’m really confused why. I mean I don’t know the logic of current “load override”.
I’m sorry to forget telling you that no value was added for /new/int at initial in my test. I know the behavior of override is to firstly delete the whole configuration and then load the new configuration. According to what you explained, since the user didn’t have delete access to /new/int, that data node would be ignored and its value kept empty. When the user loaded override file.xml, since there was no value specified for /new/int in file.xml, it was expected that no change happened on /new/int and ConfD didn’t need to do any operations to /new/int. So I would have thought even if no NACM rule for the model new, “load override” could work fine. But the result was not as expected.
Are you handling default values in your get_elem() (and get_next() etc) callbacks?
If not, that explains the behavior you observe. If you just provide the default value back to ConfD as if it was a non-default value ConfD will try to delete it when you for example use “load override” in the CLI.
Some psueudo code to illustrate how you should implement your get_elem() callback:
static int get_elem(struct confd_trans_ctx *tctx,
confd_hkeypath_t *keypath)
{
confd_value_t v;
if ("value exists and is not default") {
confd_data_reply_value(tctx, &v);
} else if ("value exists and is default"} {
CONFD_SET_DEFAULT(&v);
confd_data_reply_value(tctx, &v);
} else if ("value does not exist but the node has a default value") {
CONFD_SET_DEFAULT(&v);
confd_data_reply_value(tctx, &v);
} else { //value does not exist and the node has no default value
confd_data_reply_not_found(tctx);
}
return CONFD_OK;
}
In our implementation, no matter the node has a default value, get_elem just only calls confd_data_reply_not_found to return if value does not exist. So I think ConfD does not see a value on that node and will not try to delete it.
What is your setting for /confdConfig/defaultHandlingMode in confd.conf?
Do you have the CONFD_DAEMON_FLAG_NO_DEFAULTS flag set when you call confd_init_daemon() and/or confd_set_daemon_flags()?
This should be pointed out in other parts of the documentation too, but from the confd_lib_dp(3) man page under CONFD_DAEMON_FLAG_NO_DEFAULTS:
By default, ConfD assumes that the daemon doesn’t know about default values, and thus whenever default values come into effect,
ConfD will issue set_elem() callbacks to set those values, even if they have not actually been set
by the northbound agent.
This means that if the data provider application, like in your case, reply with confd_data_reply_not_found() when there is a default value in the YANG model but it does not exist, ConfD will try to set it. But since the user does not have access to that leaf, permission to do so will be denied.
From the confd_lib_dp(3) man page under get_elem()
If the leaf does not exist the callback must call confd_data_reply_not_found(). If the leaf
has a default value defined in the data model, and no value has been set, the callback should use
confd_data_reply_value() or confd_data_reply_value_attrs() with a value of
type C_DEFAULT - this makes it possible for northbound agents to leave such leafs out of the data
returned to the user/manager (if requested).
With your settings, if you do not want to support providing a value of type C_DEFAULT for leafs and case statements that have a default value in the YANG model, and you want to avoid the “permission denied” issue, you need to at least initialize your data provider with the default value. ConfD will then from that point on use the set_value() callback to set the default value when the leaf/case is deleted.
you need to at least initialize your data provider with the default value. ConfD will then from that point on use the set_value() callback to set the default value when the leaf/case is deleted.
I should also add CONFD_DAEMON_FLAG_NO_DEFAULTS for confd_set_daemon_flags(), then in my case ConfD will not set the default value for that leaf which defines a default value and its value doesn’t exist, right? Or could you explain further on that sentence? Thanks.
No, unless you plan on returning C_DEFAULT as described previously you should not set CONFD_DAEMON_FLAG_NO_DEFAULTS as the confd_lib_dp(3) man page describes.
For leafs and cases that have a default value in the YANG model, you either reply with an actual value or a value of type C_DEFAULT. You do not reply with confd_data_reply_not_found() for such leafs/cases