Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limitation of the storage claim #22

Open
chaen opened this issue Nov 9, 2022 · 20 comments
Open

Limitation of the storage claim #22

chaen opened this issue Nov 9, 2022 · 20 comments

Comments

@chaen
Copy link

chaen commented Nov 9, 2022

This github issue aim at illustrating the limitation we would face with the current profile when it comes to storages.

Extract from the current profile

These here are just snippet of the JWT profile in its current form, on which I base my comments below

Audience statements:

Relying parties are recommended to accept audiences based on the endpoint name most commonly associated with the provided service.
That is, if a client would want to access the resource `https://wlcg.example.com/base/file.root`, then the recommended audience for the relying party at this endpoint would be:
```
https://wlcg.example.com
```

Audiences of this form are preferred (as opposed to a human-readable "site name" such as `WLCG_Site_Foo`) to ease the ability of an end-user or tool to derive an audience from a given URL, allowing them to request an appropriate token. Site names, on the other hand, are often community-specific and would require the user to maintain a lookup table from endpoint to audience.

Path statements:

For all `storage.*` scopes, `$PATH` MUST be specified (but may be `/` to authorize the entire resource associated with the issuer); if not specified for these scopes, the token MUST be rejected. A token issuer MUST utilize absolute paths and normalize them according to section 6 of RFC 3986; as in RFC 3986, each component of the path must be URL-escaped. If a relying party encounters a non-conforming token, then it is implementation-defined if it rejects the token or performs path normalization.

Base path definition

### Example
A typical storage service must be able to map a token issuer (which corresponds to a single VO) to an area within the storage that the issuer is allowed to issue authorizations for. As an example, the XRootD implementation for JWT-based authorization has the following format:
```
[Issuer cms]
issuer = https://wlcg.example/cms
base_path = /users/cms
[Issuer dteam]
issuer = https://wlcg.example/dteam
base_path = /users/dteam
```
Here, the service administrator explicitly lists the issuers they trust (such as [https://wlcg.example/dteam](https://wlcg.example/dteam)) and restricts each to a specific directory. The technical mechanism for verifying a token based on the trusted issuer name is given in the next section.

Use case

Each LHCb user is given a logical grid directory in which he is allowed to upload files. It is of the form /lhcb/user/c/chaen. This directory exists on multiple sites.

The User StorageElements (SE) are defined as:

CERN-USER:
base_path = /eos/lhcb/prod/userarea/
GRIDKA-USER:
base_path = /pnfs/gridka.de/lhcb/userarea/
RAL-USER:
base_path = lhcb:user

A user file uploaded as the LFN /lhcb/user/c/chaen/toto.xml on the various StorageElements would end up in

CERN-USER: /eos/lhcb/prod/userarea/lhcb/user/c/chaen/toto.xml
GRIDKA-USER: /pnfs/gridka.de/lhcb/userarea/lhcb/user/c/chaen/toto.xml
RAL-USER: lhcb:user/lhcb/user/c/chaen/toto.xml

I want to issue a token that will allow the bearer to write on ALL the USER SEs

Problems

Problem with audience

The audience can in theory be a list. But if we have to list all the endpoints in the audience, the token will be huge, and we will very quickly reach the maximum header size.

Problem with the path definition

What is an absolute path ?

If the path is absolute from the storage point of view, the path should be the full physical path (i.e. /eos/lhcb/prod/userarea/lhcb/user/c/chaen/ or /pnfs/gridka.de/lhcb/userarea/lhcb/user/c/chaen/) but in that case, it is valid for one audience only.

The only sensible thing to do is to use the LFN as path: /lhcb/user/c/chaen/

But in that case, we end up with the problem of the base path definition mentioned just below.

Problems with base path definition

From a site point of view, each VO is given a base path in which the experiment can write and do anything.
For example /eos/lhcb/ at CERN, /pnfs/gridka.de/lhcb at GRIDKA. This root directory is reflected in the configuration at the site for token validation

[Issuer cms] 
issuer = https://wlcg.example/cms 
base_path = /users/cms 
[Issuer dteam] 
issuer = https://wlcg.example/dteam 
base_path = /users/dteam 

However, from the experiment point of view, this root path is often further divided.

This division can be by related to the activity, for example:

  • /pnfs/gridka.de/lhcb/userarea/ for user data
  • /pnfs/gridka.de/lhcb/prodarea/ for centraly produced data

Or it can even be divided by the various instances of the middleware, like the production and the certification instance of DIRAC:

  • /eos/lhcb/prod/userarea/ for user's data on the DIRAC production instance
  • /eos/lhcb/certification/userarea/ for the DIRAC test instance.

The second case could be discarded by simply saying that each DIRAC instance should have a separate IAM instance (fair enough).

But the first case is legitimate and poses problem. If my token contains path:/lhcb/user/c/chaen and the storage knows only /pnfs/gridka.de/lhcb as base path, the permission obviously does not point to the directory I would like it to.

Proposal

Replace the storage.*:/path approach with something along these lines

{
  "aud": "storages",
  
  "storage.modify":{
    "path": "/lhcb/user/c/chaen",
     "ses": ["CERN-USER","GRIDKA-USER","RAL-USER"]
  }
}

Contrary to what is written in

Audiences of this form are preferred (as opposed to a human-readable "site name" such as `WLCG_Site_Foo`) to ease the ability of an end-user or tool to derive an audience from a given URL, allowing them to request an appropriate token. Site names, on the other hand, are often community-specific and would require the user to maintain a lookup table from endpoint to audience.

user readable names are good because shorter (solve the header length issue). But indeed, you need a lookup table. You could imagine having this lookup table in a json file in the .well-known directory of the IAM instance in question (e.g. /.well-known/storage_definition.json)

The storage_definition.json could contain entries like:

  • For a single storage:
  "CERN-USER":{
    "base_path":"/eos/lhcb/prod/userdata",
    "host": "eoslhcb.cern.ch"
  }
  • Or a list, to shrink down even further the size of the token:
  "USER-Storages": [
  {
    "base_path": "/eos/lhcb/prod/userdata",
    "host": "eoslhcb.cern.ch"
  },
  {
    "base_path": "/pnfs/gridka.de/lhcb/userarea/",
    "host": "lhcb-gridka.fzk.ch"
  }
]

This allows even more generic token like "do anything in your user area and read all the production data"

{
  "aud": "storages",
  "storage.*": {
    "path": "/lhcb/user/c/chaen",
    "ses": "USER-Storages"
  },
  "storage.read": {
    "path": "/",
    "ses": "PROD-Storages"
  }
}

And of course, storage can make sure that the path defined in the storage_definition.json file start with the base_path they have configured.

Note that the SE definitions do not often change, so the storage systems can do aggressive caching of the definitions to validate tokens faster.

Extra bonus with this format: a token allowing third party copy between two SE could be directly handed to FTS (so no token exchange needed from its side) and would look like

{
  "aud": "storages",
  "storage.read": {
    "path": "/lhcb/user/c/chaen/toto.xml",
    "ses": "SOURCE-SE"
  },
  "storage.write": {
    "path": "/lhcb/user/c/chaen/toto.xml",
    "ses": "DEST-SE"
  }
}
@paulmillar
Copy link
Contributor

Sorry, I don't understand the problem you are facing from your description.

Audience claims
Yes, you can have multiple values but this is not recommended. In the profile you can either specify a single target (i.e., a single storage element), or use a "wildcard" value to say the token should work on all storage.

Explicit AuthZ statements (scope claims)
Could you provide a concrete example where the current JWT profile doesn't work? What file operation would you like to authorise and why doesn't it work?

@chaen
Copy link
Author

chaen commented Nov 9, 2022

Hi @paulmillar !
Please check the Use Case part. I give a very concrete example:

I want to issue a token that will allow the bearer to write on ALL the USER SEs

@paulmillar
Copy link
Contributor

Sorry, your example is not really concrete, it's actually rather abstract.

For me, a concrete use-case is something like:

Each LHCb user is assigned their own (personal) subtree within the LHCb namespace at each SE. This is somewhere a user may store their personal (non-group) files without risk of clashing with similarly named files from other LHCb users.

A LHCb user with username "fbloggs" wishes to upload a file my-latest-results.root into their personal portion of the LHCb namespace. The token should authorize this upload on any LHCb storage element.

This personal namespace is a subdirectory within a portion of the LHCb namespace used to store all LHCb users' personal subtrees.

For example, the personal subtree of the user "fbloggs" at storage element SE-1 is the directory f/fbloggs/, relative to some directory dir-X/ (where dir-X is a placeholder value). Similarly, another user "chaen" at the same storage element (SE-1) has a personal subtree under the directory c/chaen/, relative to the same directory (dir-X/). This is true for all LHCb storage elements, although the path dir-X/ will (in general) be different on different storage elements.

In general, the directory for all LHCb users' personal storage (the dir-X placeholder value, in above example) varies between different SEs.

For example, at CERN it is userdata/, at KIT it is userarea/, at RAL it is user/. These example paths are relative to some base path, which has been allocated for all LHCb storage. The base path (allocated for all LHCb storage) at KIT is /pnfs/gridka.de/lhcb/, the base path at CERN is /eos/lhcb/prod/, and the base path at RAL is lhcb:.

Discussion

If I understood the problem correctly (and the above use-case accurately describes the desired behaviour) then we have a few ways of supporting this.

  1. LHCb adopts a common approach to storing user's data.

If LHCb (quite reasonably) would like uniform behaviour then it should lay out files in a uniform way. This would require LHCb to undergo a storage reorganisation campaign. IMHO, this is not unreasonable as other VOs have undertaken similar reorganisation campaigns.

  1. Give up on the requirement that a token should work on all SEs.

It may be desirable for a token to be "tied down" so it can only work with a specific storage element. This is purely for security considerations: limiting the damage if the token is "stolen" (leaked). If this is done then the problem goes away: the token can contain the correct authorisation path for the targeted storage element.

  1. Storage software support more sophisticated AuthZ mapping.

The mapping between the "authorisation path" (i.e., the path /foo/bar from the explicit AuthZ statement storage.modify:/foo/bar) and the storage namespace (the directory into which files are upload; e.g., /pnfs/gridka.de/lhcb/foo/bar) is not specified in the JWT profile.

At least in dCache, this mapping currently assume a simple prefix: all AuthZ paths are resolved against a common base path to determine the namespace path (e.g., storage.modify:/foo/bar authorises writing into /pnfs/gridka.de/lhcb/foo/bar, by resolving the AuthZ path against a common base path of /pnfs/gridka.de/lhcb).

So, one solution could be for storage elements to provide a more sophisticated AuthZ-to-namespace mapping.

To be more concrete, one way to do this is to support a placeholder initial path-element in the AuthZ path to represent the LHCb user-space base path.

For example, the token would have a scope claim that contains storage.modify:USERS/f/fbloggs. The path element USERS is a placeholder value that maps to /eos/lhcb/prod/userdata/ at CERN, and maps to /pnfs/gridka.de/lhcb/userarea/ at KIT, etc.

In this way, an AuthZ statement would work in a uniform way across storage elements, despite the transfer namespaces being non-uniform.

Personally, I would prefer 1. or 2. over 3 to avoid unnecessary complexity in the storage (my own self-interest ;-). However, all three options would solve the LHCb user data access without requiring any changes to the JWT profile.

@paulmillar
Copy link
Contributor

Just to add some further thoughts:

There may be other solutions to this problem that are supported by the JWT profile. The above three are just the ones I could think of :-)

Of course, we can modify the JWT profile to support the LHCb use-case (in line with @chaen 's suggestion). However, I think we should first explore the above options and understand why are not possible.

Finally, the first option ("1. LHCb adopts a common approach to storing user's data") might not be too bad, at least for "regular" (non-object-store) storage. Such a move (to adopt a WLCG-wide canonical convention) could involve renaming a directory and adding a symbolic link for backwards compatibility. This could be done (more or less) atomically. Existing references would continue to work (via the sym-link).

@chaen
Copy link
Author

chaen commented Nov 28, 2022

Hi @paulmillar
Sorry for the silence, I was off since I wrote this issue :-)
You perfectly understood the problem, but you are obviously better than me at expressing it :-)

1. LHCb adopts a common approach to storing user's data.

that seems like a fair suggestion, and I am totally willing to do it (I sort of had it in mind already :-)).

I am not entirely sure that it solves everything though. For example, we have storages with and without user space.
How should I generate a token allowing me to read from all storages, but only write to storages with a user space ?

Also you mention

Finally, the first option ("1. LHCb adopts a common approach to storing user's data") might not be too bad, at least for "regular" (non-object-store) storage.

RAL is already a special case, and that alone is a reason to consider a broader scope from the beginning.

In the case of a uniform namespace, the question I raise about the path definition has an answer: what goes in path should be <placeholder>/<LFN>.

2. Give up on the requirement that a token should work on all SEs.

That is a matter of trade of between security and operational aspects. We can do a very detailed risk assessment but a token allowing a user to write to his own user space only (and not to his colleague's) is already a huge improvement compared to proxies. And we consider this a good middle ground. So we are not willing to give up on that.
There is another aspect not to forget (I don't want to multiply the examples here though): applications may be talking to multiple storages at once (think of hadd for example). So we need a generic way to express that.

3. Storage software support more sophisticated AuthZ mapping.

Your proposal of having a place holder in the path is interesting. It basically boils down to having the logical storage element definition on the storage itself, and not in a centralized dynamic json like I mentioned.

In a way, this is closer from what cloud provider (and RAL!) do: you not only write to an endpoint, but you also specify a bucket.

I think that would solve a lot of issues in how we express permissions.

I see 2 drawbacks (if we may even call it that):

  • It requires the site admin to configure the space for the VO (and not only the very top root directory). I don't think it is a problem though, regarding how infrequent these changes are.
  • Similar to my comment in point 1 regarding different permissions for different audiences in the same token: you could not generate a token that allows read from S1 and write to S2, which would have been perfect for FTS. You would necessarily have write for both. Note that it is not a big problem, as it already is an improvement compared to the current proxy model

@vokac
Copy link

vokac commented Dec 8, 2022

For Third-Party-Copy you can generate two independent tokens for source and destination storage (they could be even cached and reused by FTS). Originally our FTS design used just one token for whole FTS TPC transfer (current implementation), but I always thought it would be better to use two independent tokens, because on one side it is sufficient to use storage.read while the other side needs privileges for writing.

@msalle
Copy link

msalle commented Dec 9, 2022

For Third-Party-Copy you can generate two independent tokens for source and destination storage (they could be even cached and reused by FTS). Originally our FTS design used just one token for whole FTS TPC transfer (current implementation), but I always thought it would be better to use two independent tokens, because on one side it is sufficient to use storage.read while the other side needs privileges for writing.

but the source will need both tokens: it needs to receive the read token but also be able to send the write token. Only the destination needs just the write token?

@vokac
Copy link

vokac commented Dec 9, 2022

For Third-Party-Copy you can generate two independent tokens for source and destination storage ...

but the source will need both tokens: it needs to receive the read token but also be able to send the write token. Only the destination needs just the write token?

Yes, both tokens are available for active TPC party, but only one token reach passive party.

HTTP-TPC pull: active party is destination storage which GET data from source (read token)
HTTP-TPC push: active party is source storage which PUT data to the destination (write token)

Compromised tokens gives write privileges to one storage, not both as in case of token with read+write scope and two audiences

{
  "wlcg.ver": "1.0",
  "sub": "84622f21-a31a-46b9-81b4-85e7841e1695",
  "aud": "https://active-tpc-party.example.com,https://passive-tpc-party.example.com",
  "nbf": 1670576459,
  "scope": "storage.modify:/transfer/destination/path storage.read:/transfer/source/path",
  "iss": "https://atlas-auth.web.cern.ch/",
  "exp": 1670580059,
  "iat": 1670576459,
  "jti": "129a07b0-d59c-4fb9-bd4d-e8d602d465a0",
  "client_id": "e9b44f9d-c745-4860-bedc-dbb2c9a82fba"
}

E.g. if one storage is compromised than HTTP-TPC pull mode still prevent data destruction on the rest of distributed storage infrastructure.

@maarten-litmaath
Copy link
Collaborator

Hi all,
for storage, the WLCG profile is only concerned with a VO's namespace under an SE-specific path prefix.

Though historically, the VO probably needed to know and include such prefixes more often than not, with tokens we have an opportunity to do away with such encumbrances.

During the transition period, legacy methods (X509 + VOMS) should continue being able to use legacy (i.e. full) paths, while for tokens, each SE should be configured to add VO prefixes implicitly.

W.r.t. targeting multiple SEs with a single token, it is true that any damage from an abused token can be limited to the path(s) explicitly listed. However, in the case at hand, a VO probably would not want user directories to be created on a tape SE! The VO data management client SW should not propose such SEs to random users, of course, but we would like it better if such attempted operations would be guaranteed to fail. Unfortunately this clashes with the wish for leading directories to be created automatically as needed. As a compromise, we could forbid such automatic creations in the root directory of the VO, i.e. at least the primary leading directory (e.g. "/users") should already exist...

@vokac
Copy link

vokac commented Feb 22, 2023

Do you expect that all storage endpoints should always provide path starting with VO prefix, e.g. /atlas and that we should not accept in future arbitrary prefixes like /dpm/cern.ch/home/atlas or /eos/atlas?

Second issue with tokens that can create e.g. /vo/users on all SEs was also discovered by other experiments (e.g. ATLAS, CMS), because just limited number of SEs in our infrastructure really provide dedicated space for e.g. local users or physic groups. I think the question is if this should be part of WLCG profile & implemented by each SE or we just need more flexible policies in the token provider to allow tokens with storage.modify:/users scope only for specific aud content.

@maarten-litmaath
Copy link
Collaborator

Hi Petr,
I think it would be the nicest if the root directory for a VO were just "/" instead of "/VO_name", but the latter convention would allow one VO to access data from another, should that be necessary for some use case...

On your second point, we would need to discuss with the IAM (and CILogon) devs to see if support for such restrictions can be implemented without too much hassle. And if so, decide if such usage is going to be a sustainable way for a typical VO to limit what can be done on particular sets of SEs. For example, the VO might need to list many SE names explicitly for various use cases: not nice... It would be easier if there were support for prohibitions as well. For example, storage.modify:/users is not permitted on a given set of tape SEs... Given those various potential complications, it might be more practical just to forbid automatic primary directory creation instead.

@paulmillar
Copy link
Contributor

Do you expect that all storage endpoints should always provide path starting with VO prefix, e.g. /atlas and that we should not accept in future arbitrary prefixes like /dpm/cern.ch/home/atlas or /eos/atlas?

Let's say there are three storage systems that provide storage capacity to ATLAS. They each provide this storage under different paths: /pnfs/desy.de/atlas, /dpm/cern.ch/home/atlas and /eos/atlas. A token with a scope claim value containing storage.modify:/foo would allow the bearer to modify files under /pnfs/desy.de/atlas/foo on the first storage system, modify files under /dpm/cern.ch/home/atlas/foo on the second storage system and modify files under /eos/atlas/foo on the third storage system.

In general, there is a VO-specific prefix (e.g., /dpm/cern.ch/home/atlas). The "authorisation path" (e.g., /foo in storage.modify:/foo) is resolved relative to this VO-specific prefix. This VO prefix is potentially different for different storage services and it's something the VO has (somehow) to know. However, this is no different to what the VO needs to know currently.

I'm assuming that if a storage system provides storage capacity for other VOs then they do so under a different path (for example, /pnfs/desy.de/cms, /dpm/cern.ch/home/cms and /eos/cms for the three example storage services above). If so, then the ATLAS token would never grant any access to that other VOs storage capacity. It doesn't matter what prefixes are placed in the ATLAS token's scope claim: an ATLAS token can never grant access to CMS storage.

@maarten-litmaath
Copy link
Collaborator

Hi Paul,
the fact that VOs have needed to know those prefixes for legacy access does not imply they will need to continue to know them for the use of tokens. By your own argument (and according to our profile), storage.modify:/foo applies to /foo below the prefix (a.k.a. root directory) for the VO in question. Therefore, the prefix might as well be opaque and we should aim for that to happen with tokens. That said, we might prefer the VO namespace to start at "/VO_name" instead of "/" to allow data to be shared between VOs... Am I missing something?

@paulmillar
Copy link
Contributor

the fact that VOs have needed to know those prefixes for legacy access does not imply they will need to continue to know them for the use of tokens

While we may aspire to do better, the fact that VOs already handle per-SE prefixes means this is a solved problem. In other words, this isn't a show-stopper.

By your own argument (and according to our profile), storage.modify:/foo applies to /foo below the prefix (a.k.a. root directory) for the VO in question.

Yes. This is simply resolving the AuthZ path relative to per-VO prefix. In other words: /foo resolved-against /dpm/cern.ch/home/atlas --> /dpm/cern.ch/home/atlas/foo.

Therefore, the prefix might as well be opaque and we should aim for that to happen with tokens.

Currently (with VOMS and tokens), the request path reflect the "real" path within the storage system; for the /dpm/cern.ch/home/atlas/foo example, this might be:

curl -L -T my-output.root -H "Authorization: Bearer $MY_JWT" https://dpm.example.org/dpm/cern.ch/home/atlas/foo/my-output.root

IIRC, the JWT profile doesn't mention any changes to the request path (the /dpm/cern.ch/home/atlas/foo/my-output.root in above example).

If I've understood your comment, you are suggesting that the request path should avoid the prefix. Following this idea, the above example curl command would be:

curl -L -T my-output.root -H "Authorization: Bearer $MY_JWT" https://dpm.example.org/foo/my-output.root

I think this only makes sense if it is done for all token-based requests (including request made with tokens that have no explicit AuthZ statements). Currently, services are free to ignore explicit AuthZ statements (using group-membership instead). Therefore, we would only get consistent behaviour if this mapping were done for all token-based requests.

As it happens, dCache allows the admin to configure a per-user, chroot-like path. When this feature is enabled, all requests from that user are interpreted relative to some prefix (with no possibility to escape). If so configured, an ATLAS user could upload a file targeting the /foo/my-output.root path and dCache would store that file as /pnfs/desy.de/atlas/foo/my-output.root. All other operations (download, directory listing) work similarly; in other words, the user never knows that they are working within a sub-tree of dCache's namespace.

The dCache instance may be configured so that CMS users experience a different chroot path. Therefore,
a CMS user (on the same dCache instance) could make the same request (targeting /foo/my-output.root) but using a CMS token. The file would be stored as /pnfs/desy.de/cms/foo/my-output.root.

So, this is possible with dCache.

However I don't know if this would be supported by all storage systems. Also, it would require some kind of campaign, where this change is enacted SE-per-SE, with corresponding changes in the VO catalogues: a non-trivial effort. Therefore, I think this is something would require more discussion.

This is also rather tangential. It is (perhaps) a nice-to-have feature, but I don't see this as a show-stopper. We could do this after AuthZ tokens are in use.

That said, we might prefer the VO namespace to start at "/VO_name" instead of "/" to allow data to be shared between VOs... Am I missing something?

Well, technically you're right: this is possible. We can choose any (self-consistent) mapping between AuthN namespace and the filesystem namespace.

However, a couple of things you might like to consider.

  1. I believe we deliberately avoided talking about multi-VO use-cases. If we want to include this (particularly in a single token) then (IMHO) it needs a much broader discussion than taking only about the AuthN namespace.
  2. An alternative approach for someone who's a member of two VOs is to have two tokens: one from each of the VO's OP; for example, use the CMS token when interacting as a member of CMS and the ATLAS token when interacting as a member of ATLAS. While slightly more awkward for the user, it is conceptionally much simpler and would work with the existing JWT profile.
  3. Having a single token that asserts information from multiple VOs breaks our assumption that each VO has its own OP (should the CMS OP start asserting that someone can access ALICE files?). This would require a strong trust relationship between all VOs, and would require quite some effort to implement.

Expanding on the first point, all VO-related information (group-membership, SE AuthZ, CE AuthZ, etc) would need the token to identify for which VO they apply. Currently the VO is clear: a token issued by the ATLAS OP asserts ATLAS-related information (the asserted groups are ATLAS groups, the asserted AuthZ statements apply to ATLAS resources, etc). If we have a multi-VO tokens then a token could include information (group-membership, AuthZ statements) about CMS and about ALICE and DUNE and ...

To my mind, this breaks the JWT profile, as its currently written: the document provides no standard way for a token to describe for which VO a particular group or AuthZ statement applies.

Interestingly, the group-membership syntax coming from AARC (AARC-G02, IIRC) includes a group namespace concept. This would allow a single token to assert both CMS- and ATLAS group-membership. If we really want to support multi-VO tokens then adopting the AARC group-membership representation would be one possible solution.

That still leaves the AuthZ statements, which would need to identify for which VO's resources the AuthZ statement applies. We can do this in an ad-hoc fashion (e.g., by adding the VO in the AuthZ path), but a better approach might be to reconsider the syntax and provide a more general solution: one that could work for computing resource AuthZ statements, too.

So, yes, we could add the VO name in the AuthZ path. However, we should think really really hard before doing so.

@chaen
Copy link
Author

chaen commented Nov 10, 2023

Coming back on that after a long time, and discussions with multiple people (e.g Rucio/IAM dev) and other experiments.

Whether we like it or not, namespaces will not be uniform across storages (again confiremd by discussions during the DC workshop):

  • many experiments have legacy data, and they either don't want to move, or cannot because of the effort it requires. Some sites may even not provide the support for it.
  • it may be a design choice (e.g. I want user files only at T1, not at T2)

So the assumption namespace is uniform does not hold, and we can't rely on it (nor DIRAC nor Rucio)

After discussing with Rucio/IAM people, I would like to propose a much lighter approach to solve that.

What DIRAC/Rucio store in the config is

"DESY-SCRATCH"
{
    "prefix" : "/pnfs/desy.de/atlas/scratch/"
}
"CERN-SCRATCH"
{
    "prefix" : "/dpm/cern.ch/home/atlas/anythinggoes/"
}

Currently, if I want to read an LFN called myFile.root, I need a token that specified

For DESY

"storage.read:/scratch/mylfn.root"

FOR CERN

"storage.read:/anythinggoes/mylfn.root`"

so basically you need to put as path <prefix-voroot>/<lfn>

Not only is voroot not necessarily known (and even if we can get it, that's yet another info which is not yet part of DIRAC/Rucio config) but we saw it breaks across non uniform namespace.

At the storage level, if I understand properly, what is done is just to make sure that the issuer is allowed operation in <voroot / path_in_token> (which boils down to <prefix / lfn>)

From the semantic point of view, for DIRAC/Rucio, prefix or voroot are meaningless. What we want is to act on a given LFN stored in a SCRATCH space, be it specifically at DESY, or specifically at CERN, or in any of the two.

You could express it like

storage.read:$SCRATCH$/mylfn.root

and if you specifically want CERN or DESY, you can use the audience to restrict it.

And this is the addition I would like to propose. It's not a change, it's an addition. Support these area alias like $SCRATCH$

This would allow to very easily support non uniform namespaces, without breaking the existing functionality.

From the storage point of view, the parsing would not be very different to what is already implemented.

What is required though is the propagation of the information of what $SCRATCH$ corresponds to at the various sites, such that the storage have access to this information.

The best place would be a .well-known/se-configuration endpoint in the issuer.

"CERN":
{
   "SCRATCH" : "/dpm/cern.ch/home/atlas/anythinggoes/",
   "MC": "/dpm/cern.ch/home/atlas/mcdata/",
   "USER": "/dpm/cern.ch/home/atlas/user/",
},
"DESY":
{
  "SCRATCH" : "/pnfs/desy.de/atlas/scratch/",
   "MC":  "/pnfs/desy.de/atlas/mcdata/"
}

I believe that this is a minor addition, but which solves a lot of issues.

cc: @giacomini, @bari12, @dchristidis

@msalle
Copy link

msalle commented Nov 12, 2023

I'm probably missing something important but why isn't anything under the VO namespace (so after let's say /pnfs/desy.de/atlas for DESY and /dpm/cern.ch/home/atlas for CERN) completely up to the VO? Personally I also think it MUST be the same for each SE, if it isn't I don't understand why not, at least not from the perspective of our profile.

Trying to impose things like $HOME, $TMP, etc on top of a VO prefix seems like unnecessary complications that shouldn't be in the profile (if a VO wants to do that for its own namespace part that's not up to us of course).

@chaen
Copy link
Author

chaen commented Nov 13, 2023

Personally I also think it MUST be the same for each SE

The token profile comes 15 years after experiments started writing data. As a matter of a fact, discrepancies between SEs exist, and they wont be fixed

@giacomini
Copy link

We have discussed the matter between IAM/StoRM developers and StoRM deployers and our preference would be that the scope path prefix-matches the path in the URL, without any assumptions about the VO-based mapping, i.e. if you want to GET https://storage.example.com/vo/dir/file.txt the scope has to be storage.read:/vo/dir/file.txt or storage.read:/vo/dir or storage.read:/vo or storage.read:/. This would make it very apparent if a scope permits an operation, without hidden assumptions (almost), which I think is a good thing for authorization.
This would also enable a use case that I haven't seen discussed above: a VO having more than one entry-point at a storage endpoint, as discussed in #45 (comment).
However, if I understand correctly, this is exactly the uniform namespace solution, which @chaen says is impractical, right?

On the other hand, I'm not sure I understand the proposal of using the aliases.

  1. when you say that the scope is storage.read:$SCRATCH$/mylfn.root do you mean that that string is literally in the token?
  2. if so and assuming IAM is modified to issue such tokens (I doubt it would be easy and quick), who is the recipient of such a token? Rucio, FTS or the storage?
  3. if it is the storage, I suppose it needs a mapping mechanism similar to what is done now for a path (at least that's how StoRM works). So, why don't just use a path (e.g /lhcb/scratch) instead of an alias?

Depending on the answers, I may have also further doubts about the distribution mechanism of the aliases via the token issuer.

@chaen
Copy link
Author

chaen commented Dec 6, 2023

  1. yes, literally
  2. Storage endpoints
  3. Correct, it needs a mapping. And just using a path /lhcb/scratch requires the uniform namespace, which is impossible.

Can you share your concern with having an extra well-known endpoint in the token issuer ? We could also have this well-known hosted somewhere else (DIRAC or Rucio), providing something in the token-issuer redirects to it.

@chaen
Copy link
Author

chaen commented Jan 25, 2024

let me bring up that issue again, as the problem is still there :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants