NACM rule to restrict access to an element in list

Hello,
I’ve a data model that is a list of elements, say below

list access-list 
{
                key id;
                leaf id {
                     type string;
               }
               leaf name {
                     type string;
               }
               ..
}

I want to create rules such that, user access can be limited to one element in the list.
Say, list has 32 element and I want to create a rule that give access to element 1 of the list and deny for all others.

I created below NACM rule

/nacm:nacm/'rule-list'{test_role}/rule{test_rule}                                                       
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/0                                        
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/0/508857660 = 1323346008,             
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/action = permit, 
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/path = /access-list{1}/,
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/'module-name' = test_m,
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/'access-operations' = create 
read update delete exec,
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/tacm:context = *,

But with above rule, user (with above group) gets read access to all list elements and NO edit permission to any of the list element.

Any thoughts, what could be correct rule to restrict access to list element.

Thanks,
Manish

You can’t do exactly that (unless you know the id value in advance). The leaf path is of type node-instance-identifier, which is an XPath expression where list nodes may be restricted by predicates for keys; no other predicates are allowed. So in your case it can be either something like /access-list[id="1"] or /access-list.

If you need more complex access rules, you probably have to use authorization callbacks - see the ConfD documentation. Keep in mind that these callbacks may affect performance of your system.

@mvf Thank you so much for responding. I appreciate it.
id value is user input, so I’ve it in advance to create rule with exact id value.

I’m able to make it work using below path (as suggested by you)
/access-list[id=“1”]

Is it possible to write similar rule path for nested list.
Something like below
/access-list[id=“1”]/inner-list[in_id=“1-1”]

I tried giving above path, but it is blocking all edit access to all the elements of inner-list (including inner-list[in_id=“1-1”]).

I tried below path also, but it also block edit access to all elements to inner-list
/access-list/inner-list[in_id=“1-1”]

My actual requirement is to restrict access to an element in the inner-list.
Could you pls. help me with rule to restrict access to inner-list element.

Thanks,
Manish

That should work. With a data model corresponding to yours

  list access-list {
    key id;
    leaf id {
      type string;
    }
    leaf name {
      type string;
    }
    list inner-list {
      key in-id;
      leaf in-id {
        type string;
      }
    }
  }

and this rule-list instance

$ confd_load -F c -p '/nacm/rule-list{test-list}'
nacm rule-list test-list
 group [ oper ]
 rule test-rule
  path   /access-list[id='1']/inner-list[in-id='1-1']
  action deny
 !
!
$ 

all users belonging to the group oper are denied access to that inner-list instance.

@mvf This is working.
Earlier I was using in-id=“1-1” … that was not working.
It works with in-id=‘1-1’.
So, changing index from " to ’ worked.
I think it must be interpreting it as some regex with ".

Thank you. Appreciate your help.

-Manish

Glad it worked. In XPath expressions string literals can be enclosed in quotes (') as well as in double-quotes ("), it does not matter. But it matters for confd_cli - double-quotes have special meaning there and perhaps they have been swallowed by CLI when you entered the value.

Hello,
I need some more input. I’m creating NACM rules so that a group has access to inner-list{1-1} and inner-list{1-2} and NO access to any other element in inner-list (not even read access.

NACM rules for the same is as below to allow access to 1-1, 1-2

/nacm:nacm/'rule-list'{test_role}/rule{test_rule}                                                       
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/0                                        
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/0/508857660 = 1323346008,             
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/action = permit, 
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/path = /access-list[id='1']/inner-list[in-id=1-1'],
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/'module-name' = test_m,
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/'access-operations' = create 
read update delete exec,
/nacm:nacm/'rule-list'{test_role}/rule{test_rule}/tacm:context = *,
/nacm:nacm/'rule-list'{test_role}/rule{test_rule-6541230789-1}                                     
/nacm:nacm/'rule-list'{test_role}/rule{test_rule-6541230789-1}/0    
/nacm:nacm/'rule-list'{test_role}/rule{test_rule-6541230789-1}/0/508857660 = 1323346008,      
/nacm:nacm/'rule-list'{test_role}/rule{test_rule-6541230789-1}/action = permit,
/nacm:nacm/'rule-list'{test_role}/rule{test_rule-6541230789-1}/path = /access-list[id='1']/inner-[in_id='1-2'],
/nacm:nacm/'rule-list'{test_role}/rule{test_rule-6541230789-1}/'module-name' = test_m,
/nacm:nacm/'rule-list'{test_role}/rule{test_rule-6541230789-1}/'access-operations' = create read update delete exec,
/nacm:nacm/'rule-list'{test_role}/rule{test_rule-6541230789-1}/tacm:context = *,

Below rule to disable access to all other list elements.

/nacm:nacm/'rule-list'{test_role}/rule{deny_all_ports}                    
/nacm:nacm/'rule-list'{test_role}/rule{deny_all_ports}/0                 
/nacm:nacm/'rule-list'{test_role}/rule{deny_all_ports}/0/508857660 = 1323346008,      
/nacm:nacm/'rule-list'{test_role}/rule{deny_all_ports}/action = deny,
/nacm:nacm/'rule-list'{test_role}/rule{deny_all_ports}/path = /access-list/,          
/nacm:nacm/'rule-list'{test_role}/rule{deny_all_ports}/'module-name' = test_m,
/nacm:nacm/'rule-list'{test_role}/rule{deny_all_ports}/'access-operations' = create read update delete exec,
/nacm:nacm/'rule-list'{test_role}/rule{deny_all_ports}/tacm:context = *,   

This is working fine.
I’ve another data model that is path ref to above inner-list.

    list test {
                key "name";
                uses test-params;
    }
    grouping test-params{
        leaf name {
            type string;
            mandatory true;
       }
       leaf-list testlist{
            type leafref {
                path "/access-list/inner-list/in-id";
            }
        }
   }

same group has access to list test also.
My expectation here is that since this group has access to only in-id 1-1 and 1-2, so, for /test/newlist also, it will have access to in-id as 1-1 & 1-2.
But I see that /test/newlist has access to all the possible in-id values (not just 1-1, 1-2).

Am I missing some rule? I was assuming that since this group can only read 1-1 and 1-2 directly, so, same read permission should work for any other data model this group may have using inner-list indirectly (using path ref.

Thanks,
Manish

I think this is a misunderstanding. Access rules affect what parts of the data model or configuration tree users have access to, or what operations they can perform. Access rules do not affect validation, simply because a configuration is either valid or invalid, it cannot be valid for one user and invalid for another user.

Leafref creates an integrity constraint that is verified in validation time, so if a leafref value is valid, it is valid regardless of who configured it. If you need to restrict the leaf-list, your NACM rules would have to address the leaf-list; only I am afraid the kind of restriction you are trying to achieve cannot be expressed in NACM.

I meant access for the same user.
Say, user A has access to element id 1,2 of list test-list. It doesn’t have read access to element id 3,4.

Now for the same user, has another leaf, say, testleaf that is leafref to element id.
Are you saying that, user A can use element id 1,2,3,4 for testleaf, even though directly it can access only element 1,2 only?

I’m sorry if I’m repeating same thing again, I’m bit confused here.
I’m unable to understand, how can user A that cannot access some data directly, is able to access it indirectly (using leafref).

Thanks,
Manish

A leaf of the leafref type is effectively a leaf with the same type as that to which the statement path refers, plus the integrity constraint requiring that the value of the referring leaf must match a value of one of instances of the referred leaf. Every leafref can be rewritten as “standard” leaf with a simple must expression with exactly same behavior.

In your case it means that this model is exact equivalent of that of yours:

  list test {
    key "name";
    uses test-params;
  }
  grouping test-params {
    leaf name {
      type string;
      mandatory true;
    }
    leaf-list testlist {
      type string;
      must ". = /access-list/inner-list/in-id";
    }
  }

In other words, testlist instances in your original model are essentially strings and the user can write any value there. It is up to the transaction validation mechanism to make sure that the reference really exists, but as I wrote, this reference check ignores any access rules.

@mvf Thank you. Your detailed explanations are very helpful.

I was expecting that “must” condition to fail for element id 3,4 as this user does not have access to those instances. But, if this “must” condn ignores access rules, then, I think the only solution is what you mentioned earlier, I’ll have to write access rules this leafref.

Thanks,
Manish