dCache / dcache

dCache - a system for storing and retrieving huge amounts of data, distributed among a large number of heterogenous server nodes, under a single virtual filesystem tree with a variety of standard access methods
https://dcache.org
276 stars 134 forks source link

Support for @OP suffix for oidcgrp fields in multimap? #6450

Open sfayer opened 2 years ago

sfayer commented 2 years ago

Hi,

I was wondering if you had any plans to add support for using the @OP style suffix for oidcgrp fields in the multimap auth plugin, in a similar style to the one added to the oidc field?

I'm running a test set-up where I primarily map OIDC groups to single local users and my concern is that there could be a conflict in group names between two issuers (either accidentally or intentionally).

For clarity, I currently have two issuers enabled in gPlazma cms and other. My map file contains:

oidcgrp:/cms/production username:cmsprd
oidcgrp:/cms username:cmsusr
oidcgrp:/othervo username:vousr

What I would like to be able to specify:

oidcgrp:/cms/production@cms username:cmsprd
oidcgrp:/cms@cms username:cmsusr
oidcgrp:/othervo@other username:otherusr

That way the "other" issuer wouldn't be able to create a token for the "/cms" group and start accessing CMS data.

Perhaps there is another way that already exists to limit the group matches to a single issuer that I'm not aware of?

Regards, Simon

paulmillar commented 2 years ago

Hi Simon,

Yes, you have identified a valid concern. dCache currently doesn't distinguish groups asserted by different OPs. This can lead to the problem you describe: two OPs use the same group name (cms in your example) for different groups of people.

I've been thinking about this for a little while (to look at different solutions and gather information), but I think this really should be fixed.

I think there's actually two different issues here.

  1. There's the fact that group names (by themselves) are not necessarily unique. If you configure dCache to trust two OPs then they could (legitimately) both have the same group (for example test or local-users) but each have different membership.
  2. The two OPs both understand the group cms to mean the group of people working on data from the WLCG CMS experiment, but there are people for whom one OP asserts membership while the other doesn't.

The second one comes from an idea from AARC in their AARC-G002 guidelines document. In that document, AARC describe how to identify a group so that group names should be globally unique. This means that you could have different OPs asserting membership of the same group.

The AARC guidelines recommend a format roughly like:

<NAMESPACE>:group:<GROUP>[:<SUBGROUP>*][:role=<ROLE>]

(I've ignored the #<GROUP-AUTHORITY> part because that should be ignored when comparing group-membership and, in the draft, updated version of the document, I believe AARC plan to drop this part.)

<NAMESPACE> looks like urn:<NID>:<DEL-NAMESPACE> (e.g., urn:geant:nikhef.nl).

Here's an example of an OP that follows this format:

paul@sprocket:~$ OP=HELMHOLTZ;curl -s -H "Authorization: Bearer $(oidc-token $OP)" $(curl -s $(oidc-gen -p $OP | jq -r .issuer_url).well-known/openid-configuration | jq -r .userinfo_endpoint) | jq .eduperson_entitlement
Enter decryption password for account config 'HELMHOLTZ': 
[
  "urn:geant:helmholtz.de:group:Helmholtz-member#login.helmholtz.de",
  "urn:geant:helmholtz.de:group:HIFIS:Associates#login.helmholtz.de",
  "urn:geant:helmholtz.de:group:HIFIS#login.helmholtz.de",
  "urn:geant:helmholtz.de:group:DESY#login.helmholtz.de"
]
paul@sprocket:~$ 

That said, the (WLCG AuthZ-WG) JWT profile uses the wlcg.group claim and defines groups without any namespace. As with the groups claim, this implies the OP is (itself) the authority for the asserted groups.

Here's an example:

paul@sprocket:~$ oidc-token ESCAPE | cut -d. -f2 | base64 -d 2>/dev/null| jq ".[\"wlcg.groups\"]"
[
  "/escape",
  "/escape/pilots",
  "/escape/xfers"
]
paul@sprocket:~$ 

So, I plan to fix this by updating the OIDC group principal so each principal will contain a group namespace for that groups.

In the case of the simple groups claim and the WLCG/JWT profile's wlcg.groups claim, this would be the OP itself (which is your suggestion). For OPs that follow the AARC G002 guidelines, the namespace would be the <NAMESPACE> part of the group claim, omitting the urn: prefix.

In multimap, we then need some way of expressing the group's namespace.

I think your suggestion of @NAMESPACE is fine.

In the end, we need some way of combining two strings (the group name and the group namespace) and using some (hopefully) uncommon character makes sense.

There could be a problem if either a group's name or its namespace contains a @ character. I think either is possible, so we need a way of handling these possibilities. For example, should the statement oidcgrp:foo@bar@baz match the group foo@bar of group namespace baz, or the group foo of the group namespace bar@baz?

My suggestion for handling this is two-fold:

First, if a predicate contains multiple @ symbols then the last a @ symbol is used as a separator (e.g., oidcgrp:foo@bar@baz matches group named foo@bar from the namespace baz).

Second, the group's namespace supports percent encoding, with the rule that any @ symbol MUST be encode: @ --> %40 (e.g., oidcgrp:foo@bar%40baz matches group named foo from the namespace bar@baz).

Does that sound reasonable to you?

Cheers, Paul.

sfayer commented 2 years ago

Hi Paul,

Yes, that all sounds reasonable to me.

I would be a little suspicious of relying on the group namespace from the issuer for this purpose: I could see the potential case where a malicious issuer could deliberately use someone else's namespace in a claim, although I don't know whether that's really a legitimate problem or not.

Regards, Simon

paulmillar commented 2 years ago

Hi Simon,

Yes, you're right that an OP could (maliciously or otherwise) falsely assert group membership on an individual.

I deliberately didn't add any protection in dCache against this as I'm not yet sure how much sense it makes.

There is already a very high level of trust between the dCache admins and the people running the OP. After all, they are granting unknown users access to dCache based solely on the OP saying that they know this person.

So, does it make sense to trust an OP to identify an individual correctly, but not trust them to assert group membership correctly?

Perhaps, under some specific circumstances (depending on how much weight is placed on that person's identity). However, I'd like to see some concrete use-cases before implementing support in dCache for partially trusting an OP.

Cheers, Paul.

sfayer commented 2 years ago

Hi Paul,

Yes, I agree that it's probably not worth putting an effort into doing anything more complicated at the moment.

My view on the groups is mainly based on comparing what we had previously with the VOMS stuff... With two VOs exp1 and exp2 they could always be completely isolated from each other. Even if the exp1 VOMS server got compromised, they would never be able to touch exp2's files because the VOMS groups were always implicitly contained within the VO's namespace and couldn't be overridden (i.e. /exp1/Role=production, the "exp1" bit was pretty much immutable as it wouldn't pass verification if tampered with as the LSC files wouldn't then match).

With the OIDC stuff, it seems like with the same two VOs, if exp1's IdP was compromised there would be potential for using the namespaces to also gain access to exp2's stuff by impersonating groups with the namespace. From this perspective the only immutable bit is the local "OP" name that I (the sysadmin) assign in my config.

Perhaps it'd be possible to include both the namespace and the local OP name in the mapping? (I've not thought this through at all, so it probably has all kind of edge cases that wouldn't work): oidcgrp:<NAMESPACE>:<GROUP>@<OP>

To reiterate, I don't think it's worth spending time on this now (and I may well have misunderstood how this all fits together), just a potential scenario to think about.

Regards, Simon

paulmillar commented 2 years ago

I think I would approach this in a slightly different way, but I think the end-result would be the same.

Rather than adding the OP to the group, I would rather update the OP configuration by allowing the admin to configure which group <NAMESPACE>s that OP is authorised to assert.

So, if an OP is compromised then it couldn't assert someone has group membership outside what that OP is already authorised to add.

That way, you can still have multiple OPs that can assert the same group namespace (WLCG CMS, for example), but other OPs (WLCG ATLAS, DUNE, ...) can't assert someone is a member of CMS.