mrparkers / terraform-provider-keycloak

Terraform provider for Keycloak
https://registry.terraform.io/providers/mrparkers/keycloak/latest/docs
MIT License
607 stars 295 forks source link

removing client-level role from the client’s scope deletes all of them #838

Open filipflorek opened 1 year ago

filipflorek commented 1 year ago

Version

mrparkers/keycloak v4.2.0

Issue

Deleting one client-level role (keycloak_generic_role_mapper resource) from client's scope deletes all of them. When client A has two roles from client B assigned in it's scope, deleting one of them with terraform causes deletion of both. This issue is similar to deleting realm-level role from client's scope, which was fixed with release of mrparkers/keycloak v4.1.0

Root cause

When deleting client-level role from client's scope, Keycloak API expects roles to be passed in request body as an array. DELETE /{realm}/clients/{id}/scope-mappings/clients/{client} I believe, that as in Issue 771 the request is sent without body.

Steps to reproduce

  1. Define client backend-client and roles. backend-client is the owner of the roles.
resource "keycloak_openid_client" "backend-client-1" {
  realm_id    = "master"
  client_id   = "backend-client-1"
  access_type = "CONFIDENTIAL"
  service_accounts_enabled = "true"
}

resource "keycloak_role" "backend-1-role-1" {
  realm_id    = "master"
  client_id   = keycloak_openid_client.backend-client-1.id
  name        = "backend-1-role-1"
}

resource "keycloak_role" "backend-1-role-2" {
  realm_id    = "master"
  client_id   = keycloak_openid_client.backend-client-1.id
  name        = "backend-1-role-2"
}
  1. Define client frontend-client with full_scope_allowed set to false and add the roles to it's scope.
resource "keycloak_openid_client" "frontend-client" {
  realm_id                     = "master"
  client_id                    = "forntend-client"
  access_type                  = "PUBLIC"
  service_accounts_enabled     = false
  standard_flow_enabled        = true
  direct_access_grants_enabled = false
  enabled                      = true
  frontchannel_logout_enabled  = false
  full_scope_allowed           = false
  implicit_flow_enabled        = false
  valid_redirect_uris = ["http://localhost:9191"]
}

resource "keycloak_generic_role_mapper" "backend-1-role-1" {
  realm_id  = "master"
  client_id = keycloak_openid_client.frontend-client.id
  role_id   = keycloak_role.backend-1-role-1.id
}

resource "keycloak_generic_role_mapper" "backend-1-role-2" {
  realm_id  = "master"
  client_id = keycloak_openid_client.frontend-client.id
  role_id   = keycloak_role.backend-1-role-2.id
}
  1. Run terraform apply
  2. Remove one of the roles from frontend-client scope Plan shows that only one keycloak_generic_role_mapper resource will be deleted.
    
    # keycloak_generic_role_mapper.backend-1-role-2 will be destroyed
    # (because keycloak_generic_role_mapper.backend-1-role-2 is not in configuration)
    - resource "keycloak_generic_role_mapper" "backend-1-role-2" {
      - client_id = "e6406bcc-9ad5-4cb4-864b-ef94ff39c7f7" -> null
      - id        = "master/client/e6406bcc-9ad5-4cb4-864b-ef94ff39c7f7/scope-mappings/47e78827-84fd-4224-b50e-20b96d36b69e/0ed7131d-c235-4481-a8c2-342e1ad18f46" -> null
      - realm_id  = "master" -> null
      - role_id   = "0ed7131d-c235-4481-a8c2-342e1ad18f46" -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.


After deleting, terraform shows that only one resource was removed.

keycloak_generic_role_mapper.backend-1-role-2: Destroying... [id=master/client/e6406bcc-9ad5-4cb4-864b-ef94ff39c7f7/scope-mappings/47e78827-84fd-4224-b50e-20b96d36b69e/0ed7131d-c235-4481-a8c2-342e1ad18f46] keycloak_generic_role_mapper.backend-1-role-2: Destruction complete after 0s

Apply complete! Resources: 0 added, 0 changed, 1 destroyed.

7. Run `terraform plan`. The plan generated by terraform shows, that two `keycloak_generic_role_mapper` will be added, instead of one as expected.

keycloak_generic_role_mapper.backend-1-role-1 will be created

Plan: 2 to add, 0 to change, 0 to destroy.