Subject: [YANG] Qs about keyref

From: Andy Bierman <[email-masked]>
Date: Fri, 30 Nov 2007 10:12:51 -0800

Hi,

It is not clear what the real builtin type of a keyref object
is supposed to be.

   leaf myIfIndex {
       description "Pointer to ifIndex for interface 'eth0'";
       type keyref {
           path "/itf:interfaces/itf:interface[itf:name='eth0']/itf:ifIndex";
       }
   }

....

   <interfaces>
     <interface>
       <name>eth0</name>
       <ifIndex>42</ifIndex>
       <mtu>1500</mtu>
       ...
     </interface>
   </interfaces>

   <myIfIndex>42</myIfIndex>

So what is the XSD type of 'myIfIndex'?
Is it xs:string or itf:InterfaceIndex?

Is a keyref, by definition, a read-only object?

Clauses such as 'default', 'config', and 'units' do
not seem relevant in a typedef for a keyref data type.
What affect do they have for a keyref typedef?

Is this even legal YANG?
What if 'ifIndex' is a leaf as it is used within table X,
but not table Y?  This can happen, of course, if 'name'
and 'ifIndex' are defined in a grouping, not directly in
a list.

Why isn't this just a 'leafref' instead of 'keyref'?
The distinction between a 'pointer to a leaf used as key'
and a 'pointer to leaf not used as a key' does not seem important.

What if a user has access rights to view the 'myIfIndex'
namespace/object, but not the 'interfaces' namespace/object?

If the 'path' points to an object with QName content,
does the keyref object XML (e.g., <rpc-reply>) have to
include that prefix-to-NS mapping mapping, or is the 'pointed-at'
value considered more of an opaque string?
(This is just a variant of my first question.)

thanks,
Andy

_______________________________________________
YANG mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/yang

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 30 Nov 2007 21:17:33 +0100 (CET)

> Is it xs:string or itf:InterfaceIndex?

On the syntactical level (which is what you can define in XSD) it is
the same as itf:InterfaceIndex, whatever that is.  (then it is
restricted to the set of values existing in the configuration).

Typically you wouldn't hardcode the value of the key ('eth0') in the
DM though since that is runtime data.

> Is a keyref, by definition, a read-only object?

No!  As an typical example, I would define channelIfIndex in the RMON
MIB as a keyref.

> What affect do they have for a keyref typedef?

config I explained above.  default and units are questionable.  I'm
not sure it makes sense to add special rules to forbid them though...

> and 'ifIndex' are defined in a grouping, not directly in

The keyref will point to either table X or table Y, not to the
grouping.  So this is not a problem.

> and a 'pointer to leaf not used as a key' does not seem important.

We have discussed changing keyref into leafref.  That would make sense
in e.g. notifications (or other read-only data), but I'm not sure it
will be very useful for configuration.  As an example, suppose I do a
leafref to ifAdminStatus:

    leaf myIfAdminStatus {
        type leafref {
            path "/itf:interfaces/itf:interface/itf:ifAdminStatus";
        }
    }

  <myIfAdminStatus>up</myIfAdminStatus>

What does that mean??  

The thing here is that with the keyref you just get the key's value in
the XML, you don't get the entire instance information.  In order to
understand the relationship, you have to check the data model
definition.

Compare with SNMP - if I include ifAdminStatus in a trap, I'll get
both the instance identifier and the value in the varbind.  You won't
get that in XML unless you add both the instance identifier (XPath)
and the value as separate elements/attributes.

> namespace/object, but not the 'interfaces' namespace/object?

Then he would see that myIfIndex has the value 42.  From this he can
conclude some information, namely that an interface with ifIndex 42
exists.

> value considered more of an opaque string?

Actually, YANG doesn't have a QName type.  Maybe it should.  If we add
it, the prefix-to-ns mapping must be encoded in the reply.

/martin

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Fri, 30 Nov 2007 21:42:19 +0100

> understand the relationship, you have to check the data model

But YANG keys can be consist of several leafs so a keyref only works
nicely in some cases.

> and the value as separate elements/attributes.

Yep. And that is why the SMI notification mapping is re-introducing
all the instance identifying leafs. As I noted before, leafrefs make
the SMI notification mapping less verbose (not necessarily a prime
goal, I know). Whether the leafref make 'sense' in identifying an
'instance' is something that compilers may check.

> conclude some information, namely that an interface with ifIndex 42

I agree, we have the same in SNMP land and so far nobody had an issue
with this. The good news with yang is that you can identify an
"object" you refer to; in SMI land we had to resort to special types
to bind object types together.

/js

-- 
Juergen Schoenwaelder           Jacobs University Bremen gGmbH
Phone: +49 421 200 3587         Campus Ring 1, 28759 Bremen, Germany
Fax:   +49 421 200 3103         <http://www.jacobs-university.de/>

---

From: Andy Bierman <[email-masked]>
Date: Fri, 30 Nov 2007 13:54:19 -0800

> to bind object types together.

Well it matters to the Security Folks.
I am concerned about the access control aspects of keyref/leafref
as well, especially if it is a writable object.

Your ifAdminStatus example is a good one.
If an administrator decides that not everybody should
get to set the interface to 'down', then access control
for 'ifAdminStatus' is configured appropriately and
the security problem is addressed.   If there are other
objects that the administrator doesn't know about, that
also set the interface admin status, then a security hole exists.

It is an SNMP practice (hopefully not in YANG) to put config
parameters into the INDEX clause, to force uniqueness, for example.
So there is no real security distinction between keyref and leafref,
even though it might seem that way.

One has to assume that a hacker will know what 'myIfIndex' (or whatever)
really points to, and getting the value (42, or something sensitive,
like a password), is just as good as getting access to the real object.

Andy

---

From: Martin Bjorklund <[email-masked]>
Date: Fri, 30 Nov 2007 22:58:34 +0100 (CET)

> also set the interface admin status, then a security hole exists.

Note that the keyref/leafref is not some kind of symbolic link - if
you modify myIfAdminStatus to down, you modified just that object.
Again, compare with channelIfIndex in the RMON MIB.  keyref formalizes
what channelIfIndex has in its description clause.

> parameters into the INDEX clause, to force uniqueness

In YANG we have the 'unique' statement which is used to force
uniqueness among leaf.

/martin

---

From: Andy Bierman <[email-masked]>
Date: Fri, 30 Nov 2007 14:18:44 -0800

> what channelIfIndex has in its description clause.

Then what are the semantics of a keyref?
Copy-by-value, not copy-by-reference?

I thought it was a symbolic link.
I thought each time somebody accessed (read or write)
the keyref object, the underlying instrumentation
is really accessing the current 'pointed-to' value,
indicated by the path statement.

So this is an informative clause, like reference,
but machine-readable?  OK.   There are many times
where the data type alone is not enough (ok, it's
an InetAddress, but which one, on the device?)

So, not a security concern for writing, but what about reading?
Where does the value '42' for 'myIfIndex' come from, in this example?
I thought the agent instrumentation read 'ifIndex' and got 42.

Andy

---

From: Juergen Schoenwaelder <[email-masked]>
Date: Fri, 30 Nov 2007 23:35:36 +0100

> Copy-by-value, not copy-by-reference?

According to Martin, no copy at all. The value of a keyref is unique
to the leaf and its special semantic is that it is used to identify
some other container (and unlike the SMI, we have a way to spell out
in which container the value selects an instance).

> indicated by the path statement.

This "symbolic link" is something I would need for notifications and
it took me some time to see the difference and why keyref (or leafref)
is not really want I needed for notifications. For notifications, I
would like to really link to something in the config tree or state
tree. But as long as you stay in the config tree, this is likely not
really needed. The last time we ended with the observation that we
need both, a keyref/leafref type plus a mechanism to link stuff from
the data tree into the notification tree.

Martin, did I get this right?

/js

---

From: Martin Bjorklund <[email-masked]>
Date: Sat, 01 Dec 2007 00:02:23 +0100 (CET)

> Copy-by-value, not copy-by-reference?

Neither.  It is a reference to some key.

This is how channelIfIndex would look:

  leaf channelIfIndex {
    type keyref { 
      path "/if:interface/if:ifEntry/if:ifIndex";
    }
  }

Note:  there is no instance information at all in the path.  If you
did a get-config with the same path as xpath filter, you'd get all
ifIndexes on the box.

> I thought the agent instrumentation read 'ifIndex' and got 42.

If the app has access to channelIfIndex, it will read it and get it's
value, 42.

/martin

---

From: Martin Bjorklund <[email-masked]>
Date: Sat, 01 Dec 2007 00:27:21 +0100 (CET)

> Martin, did I get this right?

Yes, except if we can come up with some other way of doing "symbolic
links", we don't need leafrefs.  When we (you and me :) discussed
this, the best thing we came up with was to extend keyref into
leafref.   But it is still not a perfect solution...

OTOH, this problem came up when translating SNMP traps.  One problem
there is the trap may look like this:

  OBJECTS { ifIndex, ifAdminStatus, ifOperStatus }

In this case, all three objects will be from the same ifEntry
instance.  So the instance information is repeated 3 times (some may
say 4).  But if we did this trap in YANG + leafref, we would
explicitly specify that they come from the same ifEntry:

  leaf ifIndex {
    type leafref {
      path "/if:interface/if:ifEntry/if:ifIndex";
    }
  }
  leaf ifAdminStatus {
    type leafref {
      path "/if:interface/if:ifEntry"
         + "[ifIndex = $this/../ifIndex]/if:ifAdminStatus":
    }
  }
  leaf ifOperStatus {
    type leafref {
      path "/if:interface/if:ifEntry"
         + "[ifIndex = $this/../ifIndex]/if:ifOperStatus":
    }
  }
  
And an instance doc:

  <linkDown>
    <ifIndex>2</ifIndex>
    <ifAdminStatus>up</ifAdminStatus>
    <ifOperStatus>down</ifOperStatus>
  </linkdown>

The YANG spec obviously isn't perfect... but it is better than the
auto-generated one.

As an alternative, I was thinking that maybe we somehow could point
out a list entry or container, and then just list the children we want
to include in the notification.  This would be useful in notifications
and rpc-replies.

Something like this (warning: just an idea)

  notification linkDown {
    add-objects-from {
      path "/if:interface/if:ifEntry";
      include ifIndex;  // maybe the key is auto-added?  No...
      include ifAdminStatus;
      include ifOperStatus;
      include ifExtra/ifFooBar; // add from a container
    }
  }

One problem is that the add-objects-from doesn't really work like the
rest of the data definition statements in YANG...  And if you have
nested lists it's a bit trickier...

/martin