# Identity and Access Management (IAM) - 2 #### AS Lab Assignment ## Intro In this assignment, you will get familiar with fine-grained authorization services and User-Managed Access that IAM systems can provided on an example of Keycloak. Also, you will take a look on Audit capabilities of Keycloak. Submission requirements: * Report should contain: * a detailed log of your actions backed-up with screenshots * answers for questions in your **own** words * Do not erase your setup until the end of block ## Fine-grained access The simple role-based authorization approach that we have used in the previous lab may not always be enough due to its limited flexibility. With that approach, where access is checked like that: ``` fn canEdit(grant) { return grant.hasRole('editor') } ``` application is coupled with a concrete set of roles that manages access to a set of resources. If you think of a scenario, where for a concrete user we would want to forbid access to some specific resource - there is no way of doing that without modification of the original code. In order to support such cases, we may want to check access to a specific resource like that: ``` fn canEdit(grant, requestedResource) { return grant.hasAccess(requestedResource, 'edit') } ``` This approach increases the level of flexibility and decreasing the coupling - more specific rules can be defined at the side of IAM system. If there are some unexpected business requirements regarding access control, we will not need to introduce additional roles that would lead to modification of the application's code. But surely it brings complexity - rules becomes more complicated. Also, amount of resources that we now should manage separately may be very large. All that information about permissions cannot be possibly included into the access token. Thus, we have two options: perform a live verification by invoking authorization server, or include only some subset of permissions inside access token. ### 1. Create corresponding clients and enable Authorization services * `app-trainer` - It displays data taken from `api-trainer`. You have already configured it in the previous lab, but for this lab make sure that user will have `readonly` role for `api-pokemon` in token claims. * `api-trainer` - Resource server that stores data about trainer's pokemon decks. * `POST /deck-create/:deckname` * Creates a new empty trainer's deck inside in-memory store with a given name. * Also creates necessary resources in Keycloak, if they do not exist. * Returns created deck. * `GET /deck-list` * Returns all user decks from in-memory store. * `GET /deck/:username/:deckname` * Returns concrete deck. * `PATCH /deck/:username/:deckname` * Updates pokemons for concrete deck. * Returns concrete deck. * Body is a JSON array of pokemon names with length <= 6. * `DELETE /deck/:username/:deckname` * Deletes concrete deck. Authorization services are required only for the resource server. Application operates with the following resources and scopes: * resources: * `deck_create` * represents deck creation capabilities only * should be created manually * `deck_list|${username}` * represents list of decks of a particular user * created automatically * `deck|${username}|${name}` * represents concrete deck of a particular user * created automatically * scopes *(all scopes should be created manually)*: * `deck_create:create` * `deck_list:read` * `deck:read` * `deck:write` * `deck:delete` <!-- a) Analyze `api-trainer` code and come up with list of resources and scopes that are protected/created. b) Most of them a created dynamically by the resource server through Protection API that Keyclok provides, but one of them should be defined initially in Admin Console, which one? --> ### 2. Implement authorization rules Prepare *(you can skip it from the report)*: * Launch Keycloak from previous lab * Launch sample app from previous lab * Launch sample service from current lab * installation instructions inside `iam-lab-part2.zip` * do not forget to change config in `keycloak.json` with config from Installation section * note that app uses in-memory store - on restart data is wiped *(automatically created resource records in keycloak still persist)* Create necessary policies and permissions for rules: * any user with role `trainer` within `api-trainer` can create deck * only owner can read deck_list * only owner can access deck (read, write, delete) After that you should be able to add/change/delete decks in the `app-trainer`. *Hint* For debugging purposes, you can use Evaluation tool. *Hint* The "only owner" policy can be implemented as a JS type policy like that: ``` var permission = $evaluation.getPermission(); var identity = $evaluation.getContext().getIdentity(); var resource = permission.getResource(); if (resource) { if (resource.getOwner().equals(identity.getId())) { $evaluation.grant(); } } ``` <!-- To allow to uploading JS-based policies through Admin Console, Keycloak should be started with argument`-Dkeycloak.profile.feature.upload_scripts=enabled`. To keep your current data, you can fork your current docker container into a separate image using `docker commit` and run this new image with that argument. --> ## User-Managed Access #### 3. Demonstrate resource sharing User-Managed Access allows users to be in control of their resources and to decide what to share and to whom. Keycloak provides built-in account console `/realms/as_lab/account/#/resources` Use account console to demonstrate how it works: * share one of the user decks in Account Console and from another user in `app-trainer`. ## Audit #### 4. Audit capabilities As you should know, Access Control based on 3 things: Authentication, Authorization and Audit. You already got familiar with the first two. Now, learn about Keycloak audit capabilities and briefly demonstrate some of them that may be handful in incident response. ## Bonus: UMA 2.0 protocol #### 5. Learn about UMA, its main concepts and flows First, get familiar with the concepts of UMA grant flow a) What is protection API token? b) What is permission ticket? c) How does resource server create permission ticket? d) How does client use permission ticket? e) What should authorization server do with permission ticket? f) What is RPT? For reference: <https://backstage.forgerock.com/docs/am/6/uma-guide/> <https://www.keycloak.org/docs/latest/authorization_services/#_service_user_managed_access> <https://docs.kantarainitiative.org/uma/wg/rec-oauth-uma-grant-2.0.html> #### 6. Perform UMA Grant flow using `postman` (or any tool you like) UMA Grant flow allows one party to request access to the resource from another party. Support for that flow is not implemented in `api-trainer`. Suppose you would like to add it, but first, you would need to manually perform and test it. Scenario that you want to implement is the following: Suppose `User1` created a deck and `User2` wants to access that deck, in other words successfully perform `GET /deck/:username/:deckname` request. 1. On the very first request, resource server sees that permission is not granted and obtains permission ticket from the authorization server and sends it to User2 instead of the requested resource. 3. User2 tries to acquire RPT with permission ticket and receives message that requested for access is submitted. After that User2 waits. 4. At some point User1 decides to check his access requests (in the Account Console) and sees the new incoming request to his resource. 5. User1 looks at desired scopes and approves the request. 6. Now User2 can repeat it's previous actions and try to acquire RPT again. This time it should be successful. 7. User2 requests resource with RPT from the resource server and gets deck in the response. *Hint* If you are using postman - use collection variables feature for simplicity. Also, you can set variables automatically from response using "Tests" section: ``` pm.collectionVariables.set("pat", pm.response.json().access_token); ```