[rabbitmq-discuss] X.509 client authentication

Simon MacMullen simon at rabbitmq.com
Mon Jan 10 10:35:03 GMT 2011

On 07/01/11 14:06, James Casey wrote:
> what are the restrictions you have in usernames ?  Does it have to be
> a non-whitespace string ?  Are there length restrictions ?

There are no limits to the string format, and I'm not aware of any 
limits to the length.

> We're also in the situation where we have to accept 50-60 CAs (all
> with different naming structures for the DN).  We implemented
> something for activemq (where the username is just any Java string
> that can be compared against).  Here we simply did standard URI
> escaping to map into a username.  E.g for my DN:
> '/DC=ch/DC=cern/OU=Organic Units/OU=Users/CN=jamesc/CN=380618/CN=James Casey'
> I get a username of
>   '%2FDC%3Dch%2FDC%3Dcern%2FOU%3DOrganic%20Units%2FOU%3DUsers%2FCN%3Djamesc%2FCN%3D380618%2FCN%3DJames%20Casey'
> Since these are never entered directly by a user it's not such a big
> problem that they are long.  Of course if you've no problems with
> spaces, etc in a username you could just use the DN directly as the
> username.

Sure, we could use the un-uri-escaped version.

>> As soon as we start using DNs as usernames we have all sorts of problems
>> with normalisation. I'm not a real X.509 expert, but it doesn't seem like
>> there's a standard normalisation for DNs as strings. There are some
>> conventions but they seem to get very hazy once you look at issues like
>> escaping.
> I guess the 'standard' is what 'openssl x509 -subject' gives back.
> Note that the java tools work differently (elements in reversed order
> with comma separation instead of / separators.

I think the Java format is RFC 4514, which is more of a standard. What 
'openssl x509 -subject' gives back isn't documented anywhere that I can 
see. However, even if we say "use RFC 4514", that doesn't define a 
normailised representation. So we'd want to answer questions like:

* Since matching for some types of RDNs is case insensitive, should we 
covert these to lower case, upper case or what?

* Since there are multiple ways to escape, which is canonical?

This is all predicated on the idea that people will want to be able to 
predict the exact DN representation we use.

>>> I could handle storage of user details and authorization in a number
>>> of ways without any problems. I could store an external mapping of DN
>>> ->    RabbitMQ username and then let RabbitMQ do its normal
>>> authorization against the username. I could store DNs and permissions
>>> externally and have RabbitMQ do authorization call outs. I'm sure
>>> there are other ways that would work fine, too. I do want different
>>> users to have different permissions, but doing this on a per-vhost
>>> level should be enough for me.
>>> I think the main thing is how much you all want to integrate client
>>> DNs into the service vs a plugin. If you want it very integrated,
>>> DN->username mappings could be stored in the Mnesia and managed by
>>> rabbitmqctl. A user could then potentially have multiple DNs (we have
>>> this situation sometimes) and be able to authenticate using a DN or a
>>> username/password.
>> Hmm. The idea is that SASL EXTERNAL is just another way to authenticate, and
>> so it provides a username. I'm not sure a DN-to-username mapping is the best
>> way to proceed (suppose you're not storing users in Mnesia - do all auth
>> backends need to support such a mapping?)
> I think this isn't such a good idea - it's tricky mapping multiple DNs
> to the same 'user'.  Often a user has multiple DNs since he wants to
> distinguish himself this way (an DN for admin access vs a DN for
> normal access).  The issue I see here is what happens when a user gets
> a new DN after an old one expired and the CA has a policy of
> generating a new DN string (usually by appending a random number in a
> CN field.  Normally you then need admin tools to change a username,
> keeping the same permissions.

Hmm. The trouble with mapping multiple DNs to one user (from my point of 
view!) is that it makes the EXTERNAL provider stateful, and (as 
mentioned below) the state can't be assumed to reside in Mnesia.

I think I need to think about this more...

> One question here on the implementation - with an external provider
> it's only for authentication, right?  Authorization is still done by
> storing permissions in Mnesia against users ?

If you want. The "user database" part has also become pluggable on 
default, so permissions could be held in LDAP for example.

Cheers, Simon

Simon MacMullen
Staff Engineer, RabbitMQ
SpringSource, a division of VMware

More information about the rabbitmq-discuss mailing list