Skip to content

Instantly share code, notes, and snippets.

@andreaceccanti
Last active October 2, 2019 07:03
Show Gist options
  • Save andreaceccanti/e91d4e4c5f001276271869045956a756 to your computer and use it in GitHub Desktop.
Save andreaceccanti/e91d4e4c5f001276271869045956a756 to your computer and use it in GitHub Desktop.
Tokeb based authn/z for WLCG RUCIO/FTS/SEs

RUCIO/FTS TPC scenario (service identity, capability-based authz)

In this scenario, RUCIO and FTS managed transfers using their service identity.

The chain of services is

RUCIO -> FTS -> SE1, SE2

RUCIO wants to trigger transfer of file /cms/example from SE1 to SE2.

  1. RUCIO gets a token (T_fts) scoped to FTS to submit the transfer. T_fts is requested with the client_credentials flow, with the following parameters:
audience="fts"
scope="fts:submit-transfer"

This assumes that FTS implements authorization on its API taking that will take token scopes into consideration (this isn't the case now AFAIK).

  1. FTS queues the transfer. When the transfer is about to start, FTS requests a token (T_xfer) (again with client_credentials) from IAM with the following parameters:
audience="se1 se2"
scope="storage.read:/cms/example storage.create:/cms/example"`

T_xfer is used for the third-party transfer, i.e. included in the Authorization and TransferHeaderAuthorization headers.

Note that T_xfer could also be exchanged by FTS with SE-issued tokens, which would be then used for the third-party transfer.

No refresh tokens are needed. If FTS for some reason needs a fresh token, it simply goes back to IAM to fetch one.

This scenario can be supported today by IAM.

This scenario will require that all SEs can enforce audience checks and know how to map the capabilities to local authorization.

RUCIO TPC scenario (user identity, capability-based authz)

User John wants to transfer file /cms/john/example from SE1 to SE2 through RUCIO -> FTS etc.

  1. User gets an access token (T_rucio) from IAM to submit the transfer to RUCIO through its API:
audience="rucio"
scope="openid rucio:submit-transfer"

This assumes that RUCIO implements authorization on its API that will take token scopes into consideration (this isn't the case now).

  1. Now RUCIO needs to manage the transfer on behalf of John. To do so, it exchanges T_rucio with a token (T_fts) suitable to submit the transfer to FTS. This is done using the token exchange flow:
subject_token="T_rucio"
audience="fts"
scope="openid fts:submit-transfer"

Note that no refresh token is asked at this stage (probably not needed).

  1. FTS queues the transfer and exchanges T_fts with a new access token (T_xfer) and refresh token (R_xfer) to manage the transfer. The new tokens are obtained using the token exchange flow:
subject_token="T_fts"
audience="se1 se2"
scope="openid offline_access storage.read:/cms/john/example storage.create:/cms/john/example"

FTS stores R_xfer and uses it to refresh T_xfer if needed when the transfer is starting.

T_xfer (or a fresher token with equivalent privileges) is used for the third-party transfer, i.e. included in the Authorization and TransferHeaderAuthorization headers.

Note that T_xfer could also be exchanged by FTS with SE-issued tokens, which would be then used for the third-party transfer.

This scenario requires minor changes in the token-exchange flow support in IAM, which has a stricter scope validation policy in place for token-exchange.

As above, this scenario will require that all SEs can enforce audience checks and know how to map the capabilities to local authorization.

RUCIO TPC scenario (user identity, group-based authz)

User John wants to transfer file /cms/john/example from SE1 to SE2 through RUCIO -> FTS etc.

  1. User gets an access token (T_rucio) from IAM to submit the transfer to RUCIO through its API:
audience="rucio"
scope="openid wlcg.groups"

In this example flow John requests all his default groups in the default ordering. A different ordering and optional groups can be included following the rules in the WLCG JWT profile.

This assumes that RUCIO implements authorization on its API that will take user groups information extracted from the T_rucio into consideration (this isn't the case now, AFAIK).

  1. Now RUCIO needs to manage the transfer on behalf of John. To do so, it exchanges T_rucio with one suitable to submit the transfer to FTS. This is done using the token exchange flow:
subject_token="T_rucio"
audience="fts"
scope="openid wlcg.groups"

This assumes that FTS implements authorization on its API taking user groups information into account (this isn't the case now, AFAIU).

  1. FTS queues the transfer and exchanges the token obtained from RUCIO with a new access token (T_xfer) and refresh token (R_xfer) to manage the transfer. The new tokens are obtained using the token exchange flow:
subject_token="T_fts"
audience="se1 se2"
scope="openid offline_access wlcg.groups"

FTS stores R_xfer and uses it to refresh the access token obtained if needed when the transfer is starting.

T_xfer (or a fresher token with equivalent privileges) is used for the third-party transfer, i.e. included in the Authorization and TransferHeaderAuthorization headers.

Note that T_xfer could also be exchanged by FTS with SE-issued tokens, which would be then used for the third-party transfer.

This scenario can be supported today by IAM, with a caveat: groups are exposed in the "groups" claim (while the JWT profile wants "wlcg.groups"). As soon as I am done implementing the WLCG JWT profile (ETA: mid October), the scenario will be fully supported.

This scenario will require that all SEs can enforce audience checks and know how to map group information extracted from the tokens to local authz.

Notice how token exchange is mainly used to change the audience of tokens. We could reduce these exchanges if we are fine with having tokens e.g., scoped to both RUCIO and FTS, so that exchanges are needed only when offline_access needs to be requested.

Wrap up

There are two main differences with Brian's proposal:

  • when RUCIO and FTS act with their own service identity, the client credentials flow is used. No refresh tokens needed.
  • a single token, scoped at two SEs, is requested from IAM for each transfer. I think this is a reasonable tradeoff security-wise (while cutting in half the number of tokens in the IAM db) since the token is scoped and limited to access only the files transferred, and also makes more sense if IAM tokens are going to be exchanged with SE-issued tokens.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment