EntityRoleWhiteList metadata filter

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

EntityRoleWhiteList metadata filter

Tom Scavo
Apparently a MetadataFilter of type EntityRoleWhiteList [1] may be
empty, that is, it may contain zero <RetainedRole> child elements:

<MetadataFilter xsi:type="EntityRoleWhiteList">
    <!-- no child elements -->
</MetadataFilter>

That would seem to imply that no entities are retained. Is that the
correct interpretation?

OTOH, if no child elements means that ALL entities are retained, then
I claim that's a contradiction since *adding* <RetainedRole> child
elements eventually leads to the same result.

Suppose the filter required at least one <RetainedRole> child element
instead. Not only is that more clear but in that case attribute
removeRolelessEntityDescriptors becomes unnecessary since entities
with no roles would positively not be retained.

Btw, is an entity with an AffiliationDescriptor child element defined
to be a "roleless" entity descriptor? If so, all such entities would
be removed by default. Is that what happens?

Tom

[1] EntityRoleWhiteListFilter https://wiki.shibboleth.net/confluence/x/_gInAQ
--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

RE: EntityRoleWhiteList metadata filter

Rod Widdowson
> That would seem to imply that no entities are retained. Is that the
> correct interpretation?

AFAICS in the code yes.  That would be logical.  
 
> Suppose the filter required at least one <RetainedRole> child element
> instead. Not only is that more clear but in that case attribute
> removeRolelessEntityDescriptors becomes unnecessary since entities
> with no roles would positively not be retained.

I seem to remember (going back maybe 5 or 10 years) that there is religion involved with "one or more" as opposed to "zero or more"
in XML (to do with the specifications, xslt processing and some such).  

Possibly that it’s a bear to have to enforce "one or more" when auto generating XML.

I'm hoping that Ian or Scott will remember the precise details

Rod

--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

RE: EntityRoleWhiteList metadata filter

Cantor, Scott E.
> I seem to remember (going back maybe 5 or 10 years) that there is religion
> involved with "one or more" as opposed to "zero or more"
> in XML (to do with the specifications, xslt processing and some such).

Style basically, and there are hassles with one or more rules such as things breaking when you comment out the content for testing. I tend to do one or mores, and I always end up regretting it and can't seem to break myself of the habit.

-- Scott

--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Tom Scavo
In reply to this post by Rod Widdowson
On Mon, Jun 25, 2018 at 8:48 AM, Rod Widdowson <[hidden email]> wrote:
>> That would seem to imply that no entities are retained. Is that the
>> correct interpretation?
>
> AFAICS in the code yes.  That would be logical.

Okay, thanks.

What about an entity with an AffiliationDescriptor child element? I
would expect this filter to not touch that at all. Is that what
happens?

Tom
--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Cantor, Scott E.
On 6/25/18, 6:10 PM, "dev on behalf of Tom Scavo" <[hidden email] on behalf of [hidden email]> wrote:

> What about an entity with an AffiliationDescriptor child element? Icwould expect this filter to not touch that at all. Is
> that what happens?

If you tell it to keep only something with some kind of role, it's going to toss that if the entity in question doesn't have that role. That code predates anything I did and isn't compatible with it.

-- Scott


--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Tom Scavo
On Mon, Jun 25, 2018 at 7:46 PM, Cantor, Scott <[hidden email]> wrote:
> On 6/25/18, 6:10 PM, "dev on behalf of Tom Scavo" <[hidden email] on behalf of [hidden email]> wrote:
>
>> What about an entity with an AffiliationDescriptor child element? Icwould expect this filter to not touch that at all. Is
>> that what happens?
>
> If you tell it to keep only something with some kind of role, it's going to toss that if the entity in question doesn't have that role.

But there are two completely different types of entity descriptor (as
you know). Either the entity contains one or more role descriptors or
the entity contains a single affiliation descriptor. So the question
is: Should this filter completely ignore the latter?

> That code predates anything I did and isn't compatible with it.

I understand. Before I attempt to document this in jira, I need to
probe further.

To summarize: This filter excludes ALL entities that contain an
affiliation descriptor (which is the opposite of what it should do).

What about the removeRolelessEntityDescriptors attribute? What is the
filter's working definition of "roleless entity descriptor?" In any
case, why does this filter care about this?

Thanks,

Tom
--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

RE: EntityRoleWhiteList metadata filter

Cantor, Scott E.
> To summarize: This filter excludes ALL entities that contain an affiliation
> descriptor (which is the opposite of what it should do).

I don't know what it does or what it should do, you'd have to read the code in more detail than I did to this point or just test it.
 
-- Scott

--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Brent Putman
In reply to this post by Tom Scavo



On 6/26/18 12:25 PM, Tom Scavo wrote:

      
But there are two completely different types of entity descriptor (as
you know). Either the entity contains one or more role descriptors or
the entity contains a single affiliation descriptor.

Yes.  AffiliationDescriptor is not a (subtype of) RoleDescriptor, and that's how the nested <choice> elements in the EntityDescriptor define things.

 So the question
is: Should this filter completely ignore the latter?

It does completely ignore any AffiliationDescriptor if present. IIRC I didn't write it - I think Chad did.  But IMHO that's correct given its purpose.  It's the EntityRoleFilter (in OpenSAML) and the EntityRoleWhiteList in the IdP schema.  It's right there in the names.  It's about roles.  AffiliationDescriptor is not a role.


To summarize: This filter excludes ALL entities that contain an
affiliation descriptor (which is the opposite of what it should do).

No, it does not fundamentally do anything with respect to presence/absence of an AffiliationDescriptor, period.  It doesn't even look at it.

And technically the filter doesn't fundamentally "exclude" entities.  Its purpose is to remove from entities (subtypes of) RoleDescriptors which aren't in the supplied whitelist.


What about the removeRolelessEntityDescriptors attribute? What is the
filter's working definition of "roleless entity descriptor?"

"Roleless" means it doesn't contain any subtypes of the RoleDescriptor interface.  In schema terms it means it doesn't contain any elements which are effectively subtypes of md:RoleDescriptorType, which are essentially the ones in the first inner <choice> in the EntityDescriptor schema (which for the record also effectively includes extensions of RoleDescriptorType, like the concrete subtypes of QueryDescriptorType defined in the post 2.0 extension):

           <choice>
                <choice maxOccurs="unbounded">
                    <element ref="md:RoleDescriptor"/>
                    <element ref="md:IDPSSODescriptor"/>
                    <element ref="md:SPSSODescriptor"/>
                    <element ref="md:AuthnAuthorityDescriptor"/>
                    <element ref="md:AttributeAuthorityDescriptor"/>
                    <element ref="md:PDPDescriptor"/>
                </choice>
                <element ref="md:AffiliationDescriptor"/>
            </choice>


In any
case, why does this filter care about this?


Do you mean why does it have an option to remove an EntityDescriptor which doesn't have one of the whitelisted roles?  Presumably if you only want to care about (and retain) certain whitelisted roles, then an EntityDescriptor that contains none of those is of no interest to you and is just taking up space, so might as well get rid of it.

If you are filtering roles AND also actively using AffiliationDescriptors, then the above conditional about only caring about whitelisted roles isn't true, so you'd want to set 'removeRolelessEntityDescriptors' to false to retain EntityDescriptors which don't have a whitelisted role but do have an AffiliationDescriptor.


--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Tom Scavo
On Tue, Jun 26, 2018 at 2:27 PM, Brent Putman <[hidden email]> wrote:
>
> It does completely ignore any AffiliationDescriptor if present.

Great, thanks. So I added an example to the wiki that claims the
following two filters are functionally equivalent:

<MetadataFilter xsi:type="EntityRoleWhiteList"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
    <RetainedRole>md:SPSSODescriptor</RetainedRole>
</MetadataFilter>

<MetadataFilter xsi:type="Predicate" direction="include"
removeEmptyEntitiesDescriptors="true">
    <ConditionScript xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata">
        <Script>
        <![CDATA[
            input.getAffiliationDescriptor() == null &&
input.getRoleDescriptors(md:SPSSODescriptor) != null;
        ]]>
        </Script>
    </ConditionScript>
</MetadataFilter>

Do you agree? Are the above filters equivalent?

>> What about the removeRolelessEntityDescriptors attribute? What is the
>> filter's working definition of "roleless entity descriptor?"
>
> "Roleless" means it doesn't contain any subtypes of the RoleDescriptor
> interface.  In schema terms it means it doesn't contain any elements which
> are effectively subtypes of md:RoleDescriptorType, which are essentially the
> ones in the first inner <choice> in the EntityDescriptor schema (which for
> the record also effectively includes extensions of RoleDescriptorType, like
> the concrete subtypes of QueryDescriptorType defined in the post 2.0
> extension)

I wondered about that. To that end, how would you encode the following
role descriptor in a <RetainedRole> element?

<md:RoleDescriptor xsi:type="query:AttributeQueryDescriptorType">

> In any case, why does this filter care about this?
>
> Do you mean why does it have an option to remove an EntityDescriptor which
> doesn't have one of the whitelisted roles?  Presumably if you only want to
> care about (and retain) certain whitelisted roles, then an EntityDescriptor
> that contains none of those is of no interest to you and is just taking up
> space, so might as well get rid of it.

I'm confused. The EntityRoleWhiteList filter above effectively removes
all entities that do not contain an md:SPSSODescriptor role, right?
Specifically, the filter removes entire entities, it does not remove
individual roles. (If I'm wrong about that, I'm way off base.)

> If you are filtering roles AND also actively using AffiliationDescriptors,
> then the above conditional about only caring about whitelisted roles isn't
> true, so you'd want to set 'removeRolelessEntityDescriptors' to false to
> retain EntityDescriptors which don't have a whitelisted role but do have an
> AffiliationDescriptor.

An entity can't have both, so again I'm confused. I don't see any
purpose for removeRolelessEntityDescriptors.

Sorry for poking the bear but I really do want to get to the bottom of this.

Thanks,

Tom
--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Cantor, Scott E.
On 6/26/18, 5:17 PM, "dev on behalf of Tom Scavo" <[hidden email] on behalf of [hidden email]> wrote:

> Do you agree? Are the above filters equivalent?

No, because you're wrong about what the role filter does.

Also your shorthand there to specify the role to test for in the script example is unlikely to be valid, that should probably just go after the SPSSODescriptors collection directly instead of trying to access it by QName via a script. A QName would be a real Java object you'd have to create, it's not just some XML expression in the script.

> I'm confused. The EntityRoleWhiteList filter above effectively removes
> all entities that do not contain an md:SPSSODescriptor role, right?
> Specifically, the filter removes entire entities, it does not remove
> individual roles. (If I'm wrong about that, I'm way off base.)

You're off base, it removes roles. Then the flag allows it to be told to remove the entity if it no longer has any roles afterward to get it out of the set since it has no function (but if it instead contained an affiliation, that would be broken, so don't do that if that's what you're dealing with).

-- Scott


--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Brent Putman
In reply to this post by Tom Scavo



On 6/26/18 5:17 PM, Tom Scavo wrote:

Do you agree? Are the above filters equivalent?

No, per what Scott said.


I wondered about that. To that end, how would you encode the following
role descriptor in a <RetainedRole> element?

<md:RoleDescriptor xsi:type="query:AttributeQueryDescriptorType">

You would just use the QName of the xsi:type rather than the QName of the element. So:

<RetainedRole>query:AttributeQueryDescriptorType</RetainedRole>


I'm confused. The EntityRoleWhiteList filter above effectively removes
all entities that do not contain an md:SPSSODescriptor role, right?
Specifically, the filter removes entire entities, it does not remove
individual roles. (If I'm wrong about that, I'm way off base.)

As Scott said, you're off base, it removes RoleDescriptors.

In case it's not obvious: The whole point of this filter is to remove roles that are not relevant to the consuming entity.  For example, if you're an SP or discovery service, you likely only care about IDPSSODescriptors (if SP, maybe also AttributeAuthorityDescriptors).  So you'd be interested in removing all SPSSODescriptor and other roles.  If the removal of roles from an entity results in an entity with no roles, there's generally no point in keeping the entity around.  Unless you need to support consuming AffiliationDescriptors, in which case you should set the flag to not remove roleless EntityDescriptors.  As you pointed out, all entities with AffiliationDescriptors are by definition roleless.



If you are filtering roles AND also actively using AffiliationDescriptors,
then the above conditional about only caring about whitelisted roles isn't
true, so you'd want to set 'removeRolelessEntityDescriptors' to false to
retain EntityDescriptors which don't have a whitelisted role but do have an
AffiliationDescriptor.
An entity can't have both, so again I'm confused.

You're right, I spoke too quickly.  A single entity can't have both role(s) and AffiliationDescriptor.  But you certainly can have a multitude of entities with one case or the other being processed by the same filter.


 I don't see any
purpose for removeRolelessEntityDescriptors.


Hopefully the clarification that the fundamental functionality of the filter is to remove role descriptors makes the purpose more clear.

--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Tom Scavo
Wow, I don't know how I made it this far with such a faulty view of
the EntityRoleWhiteList filter. Thanks for setting me straight. Once I
recover from the shock, I'll review the wiki page and see if I can
clarify the topic without complicating it.

Tom
--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Tom Scavo
In reply to this post by Cantor, Scott E.
On Tue, Jun 26, 2018 at 5:53 PM, Cantor, Scott <[hidden email]> wrote:
> On 6/26/18, 5:17 PM, "dev on behalf of Tom Scavo" <[hidden email] on behalf of [hidden email]> wrote:
>
>> Do you agree? Are the above filters equivalent?
>
> No, because you're wrong about what the role filter does.
>
> Also your shorthand there to specify the role to test for in the script example is unlikely to be valid, that should probably just go after the SPSSODescriptors collection directly instead of trying to access it by QName via a script. A QName would be a real Java object you'd have to create, it's not just some XML expression in the script.

I see. Unfortunately the getSPSSODescriptor method takes a protocol
string argument, so that looks like a dead end, at least for my
purposes.

There is a no-argument getRoleDescriptors() method but I don't know
how to map the resulting list of RoleDescriptor objects to the
corresponding list of local names. If I knew how to do that, I could
test if the list of local names contains "SPSSODescriptor".

Thoughts?

Thanks,

Tom
--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Cantor, Scott E.
On 6/27/18, 12:13 PM, "dev on behalf of Tom Scavo" <[hidden email] on behalf of [hidden email]> wrote:

> I see. Unfortunately the getSPSSODescriptor method takes a protocol
> string argument, so that looks like a dead end, at least for my
> purposes.

I thought the Java API incuded subtype collection accessors, apparently not.

> There is a no-argument getRoleDescriptors() method but I don't know
> how to map the resulting list of RoleDescriptor objects to the
> corresponding list of local names. If I knew how to do that, I could
> test if the list of local names contains "SPSSODescriptor".

Pretty sure it's just getLocalName() but refer to the javadocs I suppose, whatever is on XMLObject should expose the relevant information. Of course that only works for named child elements and not xsi:type'd extension children but that's good enough.

-- Scott


--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Brent Putman



On 6/27/18 12:34 PM, Cantor, Scott wrote:
On 6/27/18, 12:13 PM, "dev on behalf of Tom Scavo" [hidden email] wrote:

I see. Unfortunately the getSPSSODescriptor method takes a protocol
string argument, so that looks like a dead end, at least for my
purposes.

Well, it's less convenient for your purposes than a no-arg one, but if all you practically care about is SAML 2 (and maybe SAML 1) then you can certainly call that method with the relevant protocol URI string(s) and achieve what you want.

I thought the Java API incuded subtype collection accessors, apparently not.

It does have them (e.g. getSPSSODescriptor, getAttributeAuthorityDescriptor, etc) but they all take a mandatory desired protocol, and they return the single first matching one. There are not no-arg variants that return the whole subtype collection.

I don't know why exactly that is. IIRC the metadata XMLObject code was the very first that Chad wrote way back in 2005-ish, and so probably wasn't anticipating this kind of use case.  Usually when you're looking for a specific descriptor type, you're doing in context of generating or processing a request under a specific protocol, so the existing accessors make sense for that.


There is a no-argument getRoleDescriptors() method but I don't know
how to map the resulting list of RoleDescriptor objects to the
corresponding list of local names. If I knew how to do that, I could
test if the list of local names contains "SPSSODescriptor".

What you want to look at is the XMLObject interface.  You can get the role descriptor elements' QNames via getElementQName().  And if necessary also the xsi:type QName via getSchemaType().  Then eval the QNames however you want, either by testing for equality against either a QName constant or one you have constructed (probably the most correct) or just looking at the getLocalPart() of the QName.

If using Java 8 at runtime, the most natural way to literally map the descriptor list to a new list of type QName and then evaluate it would be using lambdas.  Then that whole test becomes a one-liner. I'll list a couple of variants in pure Java below, but I don't know what syntax modifications are necessary to work in JSR-223 scripting using Javascript, etc.  In fact I don't know for sure whether and how lambdas work in scripts at all, maybe someone else does. I imagine one way or another they do, though.

Most compact, using method ref and default helper method:

        boolean found = entity.getRoleDescriptors().stream()
                .map(RoleDescriptor::getElementQName)
                .anyMatch(Predicate.isEqual(SPSSODescriptor.DEFAULT_ELEMENT_NAME));

Less compact, using full Function and Predicate lambda expressions:

        boolean found = entity.getRoleDescriptors().stream()
                .map(role -> {return role.getElementQName();})
                .anyMatch(name -> {return SPSSODescriptor.DEFAULT_ELEMENT_NAME.equals(name);});



Pretty sure it's just getLocalName() but refer to the javadocs I suppose, whatever is on XMLObject should expose the relevant information. Of course that only works for named child elements and not xsi:type'd extension children but that's good enough.

I don't think there is such a method on the interface XMLObject.  Maybe you're thinking of QName getLocalPart().  We might have a static support method somewhere that returns that however, I don't know.

Or maybe you are thinking of the 'public static final String DEFAULT_ELEMENT_LOCAL_NAME' members that we usually define. But that is more of just a convention and not a contract.



--
To unsubscribe from this list send an email to [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: EntityRoleWhiteList metadata filter

Tom Scavo
On Wed, Jun 27, 2018 at 6:11 PM, Brent Putman <[hidden email]> wrote:
>
>> Unfortunately the getSPSSODescriptor method takes a protocol
>> string argument, so that looks like a dead end, at least for my
>> purposes.
>
> Well, it's less convenient for your purposes than a no-arg one, but if all
> you practically care about is SAML 2 (and maybe SAML 1) then you can
> certainly call that method with the relevant protocol URI string(s) and
> achieve what you want.

Sure, but that's a hack I'd rather avoid.

>> There is a no-argument getRoleDescriptors() method but I don't know
>> how to map the resulting list of RoleDescriptor objects to the
>> corresponding list of local names. If I knew how to do that, I could
>> test if the list of local names contains "SPSSODescriptor".
>
> What you want to look at is the XMLObject interface.  You can get the role
> descriptor elements' QNames via getElementQName().  And if necessary also
> the xsi:type QName via getSchemaType().  Then eval the QNames however you
> want, either by testing for equality against either a QName constant or one
> you have constructed (probably the most correct) or just looking at the
> getLocalPart() of the QName.

Thanks for the useful tips.

> If using Java 8 at runtime, the most natural way to literally map the
> descriptor list to a new list of type QName and then evaluate it would be
> using lambdas.  Then that whole test becomes a one-liner.
>
> Most compact, using method ref and default helper method:
>
>         boolean found = entity.getRoleDescriptors().stream()
>                 .map(RoleDescriptor::getElementQName)
>
> .anyMatch(Predicate.isEqual(SPSSODescriptor.DEFAULT_ELEMENT_NAME));
>
> Less compact, using full Function and Predicate lambda expressions:
>
>         boolean found = entity.getRoleDescriptors().stream()
>                 .map(role -> {return role.getElementQName();})
>                 .anyMatch(name -> {return
> SPSSODescriptor.DEFAULT_ELEMENT_NAME.equals(name);});

Wonderful! I can definitely work with that.

> I don't know what syntax modifications
> are necessary to work in JSR-223 scripting using Javascript, etc.  In fact I
> don't know for sure whether and how lambdas work in scripts at all, maybe
> someone else does.

I can guess :-) JavaScript has no notion of a static member so I'll
refactor your latter example to use the local part of each QName:

input.getRoleDescriptors().stream()
        .map(function(role) role.getElementQName().getLocalPart())
        .anyMatch(function(name) name.equals("SPSSODescriptor"));

I haven't tested that but I'll bet it's close.

Thanks Brent!

Tom
--
To unsubscribe from this list send an email to [hidden email]