mrparkers / terraform-provider-keycloak

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

Panic when creating `keycloak_realm_user_profile` resource #826

Open wcislo-saleor opened 1 year ago

wcislo-saleor commented 1 year ago

Terraform: v1.3.9 terraform-provider-keycloak: 4.2.0 Keycloak: 20.0.3

Resource definition:

resource "keycloak_realm_user_profile" "userprofile" {
  realm_id = keycloak_realm.realm.id

  attribute {
    name         = "email"
    display_name = "$${email}"
    required_for_roles  = ["user", "admin"]
    required_for_scopes = []
    enabled_when_scope = []

    permissions {
      view = []
      edit = []
    }

    validator {
      name = "email"
    }

    validator {
      name   = "length"
      config = {
        max = "255"
      }
    }
  }
}

Error:

module.environment.module.keycloak.keycloak_realm_user_profile.userprofile: Creating...
╷
│ Error: Plugin did not respond
│
│   with module.environment.module.keycloak.keycloak_realm_user_profile.userprofile,
│   on ../../../modules/aws/keycloak/keycloak.tf line 13, in resource "keycloak_realm_user_profile" "userprofile":
│   13: resource "keycloak_realm_user_profile" "userprofile" {
│
│ The plugin encountered an error, and failed to respond to the plugin.(*GRPCProvider).ApplyResourceChange call. The plugin logs may contain more details.
╵

Stack trace from the terraform-provider-keycloak_v4.2.0 plugin:

panic: interface conversion: interface {} is nil, not map[string]interface {}

goroutine 58 [running]:
github.com/mrparkers/terraform-provider-keycloak/provider.getRealmUserProfileAttributeFromData(0x100fbb040?)
        github.com/mrparkers/terraform-provider-keycloak/provider/resource_keycloak_realm_user_profile.go:145 +0x1358
github.com/mrparkers/terraform-provider-keycloak/provider.getRealmUserProfileAttributesFromData({0x1400022b6c0, 0x1, 0xa?})
        github.com/mrparkers/terraform-provider-keycloak/provider/resource_keycloak_realm_user_profile.go:241 +0xb8
github.com/mrparkers/terraform-provider-keycloak/provider.getRealmUserProfileFromData(0x140001ee780?)
        github.com/mrparkers/terraform-provider-keycloak/provider/resource_keycloak_realm_user_profile.go:293 +0x68
github.com/mrparkers/terraform-provider-keycloak/provider.resourceKeycloakRealmUserProfileCreate({0x1010f4768, 0x14000621200}, 0x0?, {0x1010e68c0?, 0x14000380540?})
        github.com/mrparkers/terraform-provider-keycloak/provider/resource_keycloak_realm_user_profile.go:410 +0x98
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).create(0x140004d6ee0, {0x1010f47a0, 0x1400013a2d0}, 0xd?, {0x1010e68c0, 0x14000380540})
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.23.0/helper/schema/resource.go:707 +0xec
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).Apply(0x140004d6ee0, {0x1010f47a0, 0x1400013a2d0}, 0x1400053ed00, 0x140001ee600, {0x1010e68c0, 0x14000380540})
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.23.0/helper/schema/resource.go:837 +0x874
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).ApplyResourceChange(0x14000385608, {0x1010f47a0?, 0x1400013a1b0?}, 0x140007163c0)
        github.com/hashicorp/terraform-plugin-sdk/v2@v2.23.0/helper/schema/grpc_provider.go:1021 +0xb94
github.com/hashicorp/terraform-plugin-go/tfprotov5/tf5server.(*server).ApplyResourceChange(0x1400047a960, {0x1010f47a0?, 0x14000286e70?}, 0x140002fc070)
        github.com/hashicorp/terraform-plugin-go@v0.14.0/tfprotov5/tf5server/server.go:818 +0x3c0
github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5._Provider_ApplyResourceChange_Handler({0x1010b8060?, 0x1400047a960}, {0x1010f47a0, 0x14000286e70}, 0x140002fc000, 0x0)
        github.com/hashicorp/terraform-plugin-go@v0.14.0/tfprotov5/internal/tfplugin5/tfplugin5_grpc.pb.go:385 +0x174
google.golang.org/grpc.(*Server).processUnaryRPC(0x140004a4000, {0x1010f7340, 0x140002d2b60}, 0x14000138000, 0x1400053a690, 0x1015d24e0, 0x0)
        google.golang.org/grpc@v1.48.0/server.go:1295 +0x9d8
google.golang.org/grpc.(*Server).handleStream(0x140004a4000, {0x1010f7340, 0x140002d2b60}, 0x14000138000, 0x0)
        google.golang.org/grpc@v1.48.0/server.go:1636 +0x840
google.golang.org/grpc.(*Server).serveStreams.func1.2()
        google.golang.org/grpc@v1.48.0/server.go:932 +0x88
created by google.golang.org/grpc.(*Server).serveStreams.func1
        google.golang.org/grpc@v1.48.0/server.go:930 +0x298

Error: The terraform-provider-keycloak_v4.2.0 plugin crashed!

This is always indicative of a bug within the plugin. It would be immensely
helpful if you could report the crash with the plugin's maintainers so that it
can be fixed. The output above should help diagnose the issue.

If there is anything else I could provide to help investigate please let me know.

wcislo-saleor commented 1 year ago

I just noticed that Keycloak 20 is not supported.

mrparkers commented 1 year ago

I haven't tested Keycloak 20 yet but I should be able to confirm that it works with this provider and update the matrix that I test with. In any case, provider panics are always a bug, so thanks for opening this issue.

wcislo-saleor commented 1 year ago

FWIW (I have no idea about programming in Go)

By looking at the stack trace it seems that a variable is assumed to be not null but in fact is. I adjusted my resource definition and with the following steps I was able to stop this panic from happening.

  1. Change block
    permissions {
      view = []
      edit = []
    }

    to

    permissions {
      view = [“admin”, “user”]
      edit = []
    }
  2. terraform apply
  3. Revert the change.
  4. terraform apply
  5. Panic doesn't occur anymore.
wcislo-saleor commented 1 year ago

If this helps in any way, I encountered the same issue by doing following.

  1. Configure smtp_server settings with Terraform (including auth block).
  2. terraform apply
  3. In Keycloak Web Admin interface disable authentication for SMTP.
  4. terraform apply
  5. Panic occurred.
kasir-barati commented 1 year ago

@wcislo-saleor Would you mind if I ask you some offtopic questions:

  1. I also configured my Keycloak to have occupation and location besides having all other normal fields as you can see it here: https://github.com/kasir-barati/you-say/blob/main/keycloak/user-profile.tf but now I soloy have this in my registration page: image
  2. Not even I cannot see the first name and other inputs as I expected there is not any sign of the occupation or location. Any idea?
  3. Where I can learn more about how I can configure Keycloak with Terraform? AFAIK there are limited resources on the web and even less for Terraform + Keycloak. Please kindly advise me on this topic as well.
kasir-barati commented 1 year ago

I found the answer with a bit of patience and reading the doc. Of course google was not useful at all even for showing me the official documentation. I used lovely Tor to find it. BTW here is what I understood and what I did regarding testing it and making sure that it is the way I should do it:

Information

When you create an attribute, no permission is set to the attribute. Effectively, the attribute won’t be accessible by either users or administrators. Once you create the attribute, make sure to set the permissions accordingly to that the attribute is only visible by the target audience. (Ref)

What I did

  1. I activate the user profile and allow registration
  2. I created a new attribute with a name, display name, and required always for anyone
  3. I checked registration page, the newly created attribute was not there
  4. I set the permission for edit and view for both admin and user
  5. I checked the registration page and it was there

Here is my final terraform code:

resource "keycloak_realm_user_profile" "you-say-user-profile" {
  realm_id = keycloak_realm.you-say-realm.id

  attribute {
    name         = "firstName"
    display_name = "$${firstName}"

    permissions {
      view = ["admin", "user"]
      edit = ["admin", "user"]
    }

    validator {
      name   = "person-name-prohibited-characters"
      config = {}
    }
    validator {
      name = "length"
      config = {
        "min" : 2,
        "max" : 255
      }
    }
  }

  attribute {
    name         = "lastName"
    display_name = "$${lastName}"

    permissions {
      view = ["admin", "user"]
      edit = ["admin", "user"]
    }

    validator {
      name   = "person-name-prohibited-characters"
      config = {}
    }
    validator {
      name = "length"
      config = {
        "min" : 2,
        "max" : 255
      }
    }
  }

  attribute {
    name         = "occupation"
    display_name = "$${occupation}"

    permissions {
      view = ["admin", "user"]
      edit = ["admin", "user"]
    }

    validator {
      name = "pattern"
      config = {
        pattern       = "^[a-zA-Z0-9_][a-zA-Z0-9_ ]*[a-zA-Z0-9_]$"
        error-message = "Please use only characters and space between words, And do not start or end your occupation with white space"
      }
    }
  }

  attribute {
    name         = "location"
    display_name = "$${location}"
    validator {
      name = "pattern"
      config = {
        pattern       = "^[a-zA-Z\u0080-\u024F]+(?:. |-| |')*([1-9a-zA-Z\u0080-\u024F]+(?:. |-| |'))*[a-zA-Z\u0080-\u024F]*$"
        error-message = "Please enter a valid city name followed by the country name. e.x. Tokyo, Japan"
      }
    }
  }
}

More info in my you-say repo