docs: add ADR on keycloak authorisation service for multitenancy
Signed-off-by: Pat Losoponkul <[email protected]>
Signed-off-by: Pat Losoponkul <[email protected]>
# Use keycloak authorisation service for managing wallet permissions
- Status: accepted
- Decider: Pat Losoponkul, Yurii Shynbuiev, David Poltorak, Milos Dzepina
- Date 2023-09-26
- Tags: multitenancy, authorisation, authentication
Technical Story: [External IAM provider integration for Authentication and Authorisation Layers MVP | https://input-output.atlassian.net/browse/ATL-5149]
## Context and Problem Statement
As we move forward with multi-tenancy, it's essential to give extra attention to authentication and authorisation.
Currently, our authentication and authorisation processes are managed by a simple built-in IAM implementation within the cloud agent.
While this setup is straightforward and functional, it's a somewhat basic and proprietary approach.
Transitioning to an industry-standard IAM system like Keycloak represents an important step towards a more robust authentication and authorisation framework.
Within our multi-tenant cloud agent, we have some key concepts:
wallets (representing resources), entities (representing users), and authentication methods.
These models are integrated into our current IAM implementation within the agent allowing a loose coupling of users and resources, as well as resource access.
As we consider the shift towards an external IAM system, several important questions arise:
1. Where to draw the boundary of AuthN/AuthZ across different components?
2. How to ensure smooth communication of wallet permissions across these components?
3. What will be the impact on the process of onboarding new users and wallets?
These questions are essential as we explore the integration options of an external IAM that suits our needs.
## Decision Drivers
- Complexity to implement, operate and maintain
- Must allow self-hosted option as well as future SaaS offering
- Must allow flexible management of resources, users and permissions
- Should adhere to standards in AuthN/AuthZ space
- Should promote clear boundary between application and IAM concerns
## Considered Options
1. Keycloak for authentication and associate the wallet permissions on the Agent.
2. Keycloak for authentication and embed custom permission claims in the `access-token`.
3. Keycloak for authentication and authorisation service managing permissions.
## Decision Outcome
Use Keycloak authorisation service for managing wallet permissions.
Keycloak authorisation service offers a robust abstraction based on an industry-standard specification called UMA (User-Managed Access).
It allows us to define resources, resource owners, permissions, and policies with ease.
These concepts are tried and tested, and Keycloak provides them right out of the box, making it a suitable choice.
It is also the only option to adhere to the standard.
In this setup, applications are responsible for managing their resources and rely on
Keycloak for managing permissions on those resources.
To determine whether a user can access a specific resource, the application can simply utilise Keycloak's permission endpoint.
### On-boarding sequence diagram
```mermaid
sequenceDiagram
actor Admin
actor User
participant Client
participant PrismAgent
participant Keycloak
autonumber
Admin ->> PrismAgent: Create a new wallet
PrismAgent ->> Keycloak: Register a new resource
Admin ->> Keycloak: Create a new user
Admin ->> Keycloak: Create a new user-credential
Admin ->> Keycloak: Create a new permission
Admin ->> Keycloak: Associate permission(s) with a resource
```
### Authorisation sequence diagram
```mermaid
sequenceDiagram
actor Admin
actor User
participant Client
participant PrismAgent
participant Keycloak
autonumber
User ->> Client: First visit
Note over Client: User is not logged in
Client ->> Keycloak: Login with preconfigured flow
Keycloak ->> Client: JWT AccessToken
User ->> Client: Check my VC
Client ->> PrismAgent: Get CredentialRecord
opt Bearer token is not RPT
PrismAgent ->> Keycloak: Get permissions
Keycloak ->> PrismAgent: Permitted resource(s)
end
alt is permitted
PrismAgent ->> Client: CredentialRecord
else is not permitted
PrismAgent ->> Client: 403 Forbidden
end
```
Optionally, users or downstream applications can directly call Keycloak permission endpoint to get a RPT (requesting-party token)
to obtain a self-contained `access-token` which already include permissions.
### Positive Consequences
- Good separation between IAM and application concerns
- Powerful and proven abstraction for managing permissions
- Implementation is ready out of the box
- Easy to migrate to different IAM vendor that supports UMA specification
### Negative Consequences
- Require additional network call to obtain a permission token
- Involves more moving parts in managing wallet permissions
- Each IAM systems may have a slight variations to the UMA endpoints
## Pros and Cons of the Options
### Keycloak for authentication and associate the wallet permissions on the Agent
- Good, because permission logic is on application and allowing any IAM solution to be used regardless of authorisation feature
- Bad, because permissions are managed on the application and IAM boundary is blurred
- Bad, because engineering effort is spent on non-differentiating value in order to have feature parity with other authorisation system
### Keycloak for authentication and embed custom permission claims in the `access-token`
- Good, because the `access-token` is self-contained and doesn't require extra network call
- Good, because IAM systems are more likely to support custom claims feature
- Bad, because the custom claims are directly linked to user's attributes preventing flexible mangement of permission
## Links
- [Keycloak authorisation service](https://www.keycloak.org/docs/latest/authorization_services/index.html)
TODO: Remove SRP TODO: Bump to the latest cardano-api TODO: Bump to the latest cardano-cli
Create and submit votes on proposal
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <[email protected]>
# Description Adding fund 11 dates The idea scale importer sql file will be updated in another ticket Fixes https://github.com/input-output-hk/catalyst-core/issues/639 ## Type of change Please delete options that are not relevant. - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update ## How Has This Been Tested? Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration - [ ] Test A - [ ] Test B **Test Configuration**: _if applicable_ - Firmware version: - Hardware: - Toolchain: - SDK: **List of new dependencies**: _if applicable_ Provide a list of newly added dependencies in this PR, with the description of what are they doing and why do we need them. - Crate A: description - Crate B: description ## Checklist - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules
LW-9237 typeorm stake pool provider backward compatibility
PLT-8886 Swap the order of account and party in CanDeposit
As we removed those guards from the chain layer, it is important that the logic layer is doing this filtering.
It looks like the author mean to do: if(parser.peek() == UNSIGNED_INT) { parser.readUInt() } instead of if(parser.peek() == UNSIGNED_INT) { parser.readInt() }