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

Authorization rule changes for IDPs isolation [DPP-1336] #15848

Merged
merged 32 commits into from
Jan 12, 2023

Conversation

skisel-da
Copy link
Contributor

No description provided.

@skisel-da skisel-da force-pushed the skisel-da/identity-management-poc4 branch 4 times, most recently from 85c874d to a7d6e96 Compare December 18, 2022 16:50
@skisel-da skisel-da changed the title Identity Provider Config management rebased POC 4 Authorization rule changes for IDPs isolation Dec 20, 2022
@skisel-da skisel-da force-pushed the skisel-da/identity-management-poc4 branch from a7d6e96 to 81aced5 Compare December 20, 2022 12:55
@skisel-da skisel-da marked this pull request as ready for review December 20, 2022 12:57
Copy link
Contributor

@pbatko-da pbatko-da left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General question:

  1. Will it be possible to set up a user he admin right and in a non default idp?
  2. What if the user management service is enabled and someone uses a custom daml access token (one doesn't mention the user id). Can such a request succeed?
  3. To fetch themselves in GetUserRequest a user doesn't need to provide it's user id but it needs to provide its idp id - this seems a bit unintuitive. Maybe if we renamed the default idp from the empty string to a some other value (e.g. "default") then maybe w could make the identity_provider_id fields in the requests default to the current user's idp?

I think these changes need be accompanied by a suite authorization tests because the logic here is really non-trivial.

// Claim is valid only for the specific Identity Provider,
// and identity_provider_id in the request matches the one provided in the claim.
Left(AuthorizationError.InvalidIdentityProviderId(id))
case _ =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When claims.identityProvider is the default idp and requestIdentityProviderId is None then you're succeeding, but requestIdentityProviderId being None actually means that request idp validation failed.

I think this method should accept only valid requestIdentityProviderIds i.e. requestIdentityProviderId: IdentityProviderId

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If requestIdentityProviderId is not provided - it's NOT an authorization problem, it will be validated out in the layer below. It is an invalid argument which will be validated further. Not sure how to act here to make sure proper layers are responsible for errors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding of this code is that in line 129 Left(AuthorizationError.InvalidIdentityProviderId(id)) is returned also requestIdentityProviderId is None.

Also, could it even be the case that requestIdentityProviderId is not provided? Because if it's the empty it actually means the default idp

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me first define here what is what.

claims.identityProviderId is what is provided from the token. So two options here are possible:

  1. default IDP (token is issued by the auth config defined in the default configuration)
  2. non-default IDP having concrete value (as it is of type IdentityProviderId)

requestIdentityProviderId is what we extracted out from the request. Here we distinguish the following cases:

  1. None, means identity_provider_id from the request which cannot be recognized/parsed. For example String with more than 255 chars, or having invalid characters.
  2. Some value of non-default IDP which is equal to the IDP-ID of the token
  3. Some value of non-default IDP which is NOT equal to the IDP-ID of the token
  4. Default IDP (i.e. identity_provider_id was an empty string)

What is important to know with the authorization rules we have introduced:

  1. A participant_admin may provide any arbitrary value as IDP-ID (i.e. requestIdentityProviderId does not matter) and authorization layer should not be restricting the admin (that is why if claims.identityProviderId == Default it is giving Right(())
  2. An invalid IdentityProviderId, i.e. non-LedgerString, would give None for requestIdentityProviderId and authorization layer would allow to pass the filter (but currently only for non-Default IDP), as this is nothing to do with PERMISSION_DENIED error which can be issued here.

You're right with your statement that None gives InvalidIdentityProviderId. So PERMISSION_DENIED will be issued in the case of non-default IDP. I think I just have to fix it and pass it further to the business logic layer.

I think in general this highlights a bit broken design of the authorization layer. I don't like that in case of invalid request I'm passing things further and let it fail on the business logic. But doing it differently would break current pattern and will be much more work. Do you maybe have suggestions to improve that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would include parts of the justification in form of comment. Surely it is not the last time we will be looking at this code asking same questions as Pawel has

@skisel-da skisel-da changed the title Authorization rule changes for IDPs isolation Authorization rule changes for IDPs isolation [DPP-1336] Jan 3, 2023
@skisel-da
Copy link
Contributor Author

What if the user management service is enabled and someone uses a custom daml access token (one doesn't mention the user id). Can such a request succeed?

This should work as before. From the IDP perspective it would be as if request is coming from the default IDP.

@skisel-da skisel-da force-pushed the skisel-da/identity-management-poc4 branch from 1b42a24 to 9d23bd0 Compare January 5, 2023 11:07
Copy link
Contributor

@pbatko-da pbatko-da left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.
Are you planning to add any tests to this PR? I think it would be worth doing that

@skisel-da skisel-da force-pushed the skisel-da/identity-management-poc4 branch from 90c1c34 to a0c09a7 Compare January 5, 2023 18:21
@@ -16,7 +16,8 @@ class IdentityProviderConfigStoreMetrics(
override val registry: MetricRegistry,
) extends FactoryWithDBMetrics {

val cacheByIssuer = new CacheMetrics(prefix :+ "cache_by_issuer", registry)
val idpConfigCache = new CacheMetrics(prefix :+ "idp_config_cache", registry)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to document these new metrics in UNRELEASED.md

override def getIdentityProviderConfig(issuer: LedgerId)(implicit
loggingContext: LoggingContext
): Future[domain.IdentityProviderConfig] =
identityProviderStore.getActiveIdentityProviderByIssuer(issuer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which execution context should this run on?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

servicesExecutionContext ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think so too

@skisel-da skisel-da force-pushed the skisel-da/identity-management-poc4 branch from 0d0f3e9 to 946ad62 Compare January 12, 2023 10:44
@skisel-da skisel-da merged commit f184892 into main Jan 12, 2023
@skisel-da skisel-da deleted the skisel-da/identity-management-poc4 branch January 12, 2023 12:43
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

Successfully merging this pull request may close these issues.

3 participants