<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">On Mon, Sep 24, 2018 at 9:31 AM Colleen Murphy <<a href="mailto:colleen@gazlene.net">colleen@gazlene.net</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Mon, Sep 24, 2018, at 4:16 PM, Lance Bragstad wrote:<br>
> On Mon, Sep 24, 2018 at 7:00 AM Colleen Murphy <<a href="mailto:colleen@gazlene.net">colleen@gazlene.net</a>> wrote:<br>
> <br>
> > This is in regard to <a href="https://launchpad.net/bugs/1641625" rel="noreferrer">https://launchpad.net/bugs/1641625</a> and the proposed<br>
> > patch <a href="https://review.openstack.org/588211" rel="noreferrer">https://review.openstack.org/588211</a> for it. Thanks Vishakha for<br>
> > getting the ball rolling.<br>
> ><br>
> > tl;dr: Keystone as an IdP should support sending<br>
> > non-strings/lists-of-strings as user attribute values, specifically lists<br>
> > of keystone groups, here's how that might happen.<br>
> ><br>
> > Problem statement:<br>
> ><br>
> > When keystone is set up as a service provider with an external<br>
> > non-keystone identity provider, it is common to configure the mapping rules<br>
> > to accept a list of group names from the IdP and map them to some property<br>
> > of a local keystone user, usually also a keystone group name. When keystone<br>
> > acts as the IdP, it's not currently possible to send a group name as a user<br>
> > property in the assertion. There are a few problems:<br>
> ><br>
> >     1. We haven't added any openstack_groups key in the creation of the<br>
> > SAML assertion (<br>
> > <a href="http://git.openstack.org/cgit/openstack/keystone/tree/keystone/federation/idp.py?h=14.0.0#n164" rel="noreferrer">http://git.openstack.org/cgit/openstack/keystone/tree/keystone/federation/idp.py?h=14.0.0#n164</a><br>
> > ).<br>
> >     2. If we did, this would not be enough. Unlike other IdPs, in keystone<br>
> > there can be multiple groups with the same name, namespaced by domain. So<br>
> > it's not enough for the SAML AttributeStatement to contain a<br>
> > semi-colon-separated list of group names, since a user could theoretically<br>
> > be a member of two or more groups with the same name.<br>
> >    * Why can't we just send group IDs, which are unique? Because two<br>
> > different keystones are not going to have independent groups with the same<br>
> > UUID, so we cannot possibly map an ID of a group from keystone A to the ID<br>
> > of a different group in keystone B. We could map the ID of the group in in<br>
> > A to the name of a group in B but then operators need to create groups with<br>
> > UUIDs as names which is a little awkward for both the operator and the user<br>
> > who now is a member of groups with nondescriptive names.<br>
> >     3. If we then were able to encode a complex type like a group dict in<br>
> > a SAML assertion, we'd have to deal with it on the service provider side by<br>
> > being able to parse such an environment variable from the Apache headers.<br>
> >     4. The current mapping rules engine uses basic python string<br>
> > formatting to translate remote key-value pairs to local rules. We would<br>
> > need to change the mapping API to work with values more complex than<br>
> > strings and lists of strings.<br>
> ><br>
> > Possible solution:<br>
> ><br>
> > Vishakha's patch (<a href="https://review.openstack.org/588211" rel="noreferrer">https://review.openstack.org/588211</a>) starts to solve<br>
> > (1) but it doesn't go far enough to solve (2-4). What we talked about at<br>
> > the PTG was:<br>
> ><br>
> >     2. Encode the group+domain as a string, for example by using the dict<br>
> > string repr or a string representation of some custom XML and maybe base64<br>
> > encoding it.<br>
> >         * It's not totally clear whether the AttributeValue class of the<br>
> > pysaml2 library supports any data types outside of the xmlns:xs namespace<br>
> > or whether nested XML is an option, so encoding the whole thing as an<br>
> > xs:string seems like the simplest solution.<br>
> ><br>
> <br>
> Encoding this makes sense. We can formally support different SAML data<br>
> types in the future if a better solution comes along. We would have to make<br>
> the service provider deal with both types of encoding, but we could<br>
> eventually consolidate, and users shouldn't know the difference. Right?<br>
<br>
The only way this would make a difference to the user is if they need to debug a request by actually looking at the response to this request[1]. If we were to base64-encode the string that immediately obfuscates what the actual value is. I'm not really sure if we need to base64-encode it or just serialize it some other way.<br></blockquote><div><span style="background-color:rgb(255,255,255)"><br></span></div><div><span style="background-color:rgb(255,255,255)">Oh - yeah that makes sense. In your opinion, does that prevent us from adopting another way of solving the problem if we find a better data type?</span><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
[1] <a href="https://developer.openstack.org/api-ref/identity/v3-ext/index.html#id404" rel="noreferrer">https://developer.openstack.org/api-ref/identity/v3-ext/index.html#id404</a><br>
> <br>
> <br>
> >     3. The SP will have to be aware that openstack_groups is a special key<br>
> > that needs the encoding reversed.<br>
> >         * I wrote down "MultiDict" in my notes but I don't recall exactly<br>
> > what format the environment variable would take that would make a MultiDict<br>
> > make sense here, in any case I think encoding the whole thing as a string<br>
> > eliminates the need for this.<br>
> >     4. We didn't talk about the mapping API, but here's what I think. If<br>
> > we were just talking about group names, the mapping API today would work<br>
> > like this (slight oversimplification for brevity):<br>
> ><br>
> > Given a list of openstack_groups like ["A", "B", "C"], it would work like<br>
> > this:<br>
> ><br>
> > [<br>
> >   {<br>
> >     "local":<br>
> >     [<br>
> >       {<br>
> >         "group":<br>
> >         {<br>
> >           "name": "{0}",<br>
> >           "domain":<br>
> >           {<br>
> >             "name": "federated_domain"<br>
> >           }<br>
> >         }<br>
> >       }<br>
> >     ], "remote":<br>
> >     [<br>
> >       {<br>
> >         "type": "openstack_groups"<br>
> >       }<br>
> >     ]<br>
> >   }<br>
> > ]<br>
> > (paste in case the spacing makes this unreadable:<br>
> > <a href="http://paste.openstack.org/show/730623/" rel="noreferrer">http://paste.openstack.org/show/730623/</a> )<br>
> ><br>
> > But now, we no longer have a list of strings but something more like<br>
> > [{"name": "A", "domain_name": "Default"} {"name": "B", "domain_name":<br>
> > "Default", "name": "A", "domain_name": "domainB"}]. Since {0} isn't a<br>
> > string, this example doesn't really work. Instead, let's assume that in<br>
> > step (3) we converted the decoded AttributeValue text to an object. Then<br>
> > the mapping could look more like this:<br>
> ><br>
> > [<br>
> >   {<br>
> >     "local":<br>
> >     [<br>
> >       {<br>
> >         "group":<br>
> >         {<br>
> >           "name": "{<a href="http://0.name" rel="noreferrer">0.name</a>}",<br>
> >           "domain":<br>
> >           {<br>
> >             "name": "{0.domain_name}"<br>
> >           }<br>
> >         }<br>
> >       }<br>
> >     ], "remote":<br>
> >     [<br>
> >       {<br>
> >         "type": "openstack_groups"<br>
> >       }<br>
> >     ]<br>
> >   }<br>
> > ]<br>
> > (paste: <a href="http://paste.openstack.org/show/730622/" rel="noreferrer">http://paste.openstack.org/show/730622/</a> )<br>
> ><br>
> ><br>
> I can't come up with a reason not to do this at the moment. If we serialize<br>
> the group+domain name information in SAML, then it seems appropriate to<br>
> teach the service provider how to deserialize it and apply it to mappings.<br>
> Otherwise, does it make sense to build serialization into the identity<br>
> provider if we aren't going to use the domain name?<br>
> <br>
> <br>
> > Alternatively, we could forget about the namespacing problem and simply<br>
> > say we only pass group names in the assertion, and if you have ambiguous<br>
> > group names you're on your own. We could also try to support both, e.g.<br>
> > have an openstack_groups mean a list of group names for simpler use cases,<br>
> > and openstack_groups_unique mean the list of encoded group+domain strings<br>
> > for advanced use cases.<br>
> ><br>
> > Finally, whatever we decide for groups we should also apply to<br>
> > openstack_roles which currently only supports global roles and not<br>
> > domain-specific roles.<br>
> ><br>
> > (It's also worth noting, for clarity, that the samlize function does<br>
> > handle namespaced projects, but this is because it's retrieving the project<br>
> > from the token and therefore there is only ever one project and one project<br>
> > domain so there is no ambiguity.)<br>
> ><br>
> > Thoughts?<br>
> ><br>
> > - Colleen (cmurphy)<br>
> ><br>
> > __________________________________________________________________________<br>
> > OpenStack Development Mailing List (not for usage questions)<br>
> > Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" rel="noreferrer">OpenStack-dev-request@lists.openstack.org?subject:unsubscribe</a><br>
> > <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
> ><br>
> __________________________________________________________________________<br>
> OpenStack Development Mailing List (not for usage questions)<br>
> Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" rel="noreferrer">OpenStack-dev-request@lists.openstack.org?subject:unsubscribe</a><br>
> <a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
<br>
__________________________________________________________________________<br>
OpenStack Development Mailing List (not for usage questions)<br>
Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" rel="noreferrer">OpenStack-dev-request@lists.openstack.org?subject:unsubscribe</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
</blockquote></div></div>