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

Blank SMTP "auth" username and password cause plugin crash while configuring realm #737

Closed
alexander-bauer opened this issue Sep 20, 2022 · 2 comments

Comments

@alexander-bauer
Copy link

Exposition

Hello! I'm trying to use this excellent (and thorough!) provider to configure my Keycloak provider at home, and I'm encountering the following issue while attempting to create my first realm. The master realm already exists, and Terraform is authenticating using the admin-cli approach as the administrator to the master realm. I'm certain this is caused by the mishandling of some argument or another, so I'll try taking things out until I narrow down what it seems to be.

Log

kubernetes_namespace.auth: Refreshing state... [id=auth]
helm_release.keycloak: Refreshing state... [id=keycloak]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # keycloak_realm.primary will be created
  + resource "keycloak_realm" "primary" {
      + access_code_lifespan                     = (known after apply)
      + access_code_lifespan_login               = (known after apply)
      + access_code_lifespan_user_action         = (known after apply)
      + access_token_lifespan                    = (known after apply)
      + access_token_lifespan_for_implicit_flow  = (known after apply)
      + action_token_generated_by_admin_lifespan = (known after apply)
      + action_token_generated_by_user_lifespan  = (known after apply)
      + browser_flow                             = (known after apply)
      + client_authentication_flow               = (known after apply)
      + client_session_idle_timeout              = (known after apply)
      + client_session_max_lifespan              = (known after apply)
      + direct_grant_flow                        = (known after apply)
      + display_name                             = "<Redacted>"
      + display_name_html                        = "<b><Redacted></b>"
      + docker_authentication_flow               = (known after apply)
      + duplicate_emails_allowed                 = (known after apply)
      + edit_username_allowed                    = (known after apply)
      + enabled                                  = true
      + id                                       = (known after apply)
      + internal_id                              = (known after apply)
      + login_theme                              = "base"
      + login_with_email_allowed                 = true
      + oauth2_device_code_lifespan              = (known after apply)
      + oauth2_device_polling_interval           = (known after apply)
      + offline_session_idle_timeout             = (known after apply)
      + offline_session_max_lifespan             = (known after apply)
      + offline_session_max_lifespan_enabled     = false
      + password_policy                          = "length(16) and notUsername"
      + realm                                    = "<redacted>"
      + refresh_token_max_reuse                  = 0
      + registration_allowed                     = (known after apply)
      + registration_email_as_username           = (known after apply)
      + registration_flow                        = (known after apply)
      + remember_me                              = (known after apply)
      + reset_credentials_flow                   = (known after apply)
      + reset_password_allowed                   = true
      + revoke_refresh_token                     = false
      + ssl_required                             = "all"
      + sso_session_idle_timeout                 = (known after apply)
      + sso_session_idle_timeout_remember_me     = (known after apply)
      + sso_session_max_lifespan                 = (known after apply)
      + sso_session_max_lifespan_remember_me     = (known after apply)
      + user_managed_access                      = true
      + verify_email                             = true

      + internationalization {
          + default_locale    = "en"
          + supported_locales = [
              + "en",
            ]
        }

      + otp_policy {
          + algorithm         = (known after apply)
          + digits            = (known after apply)
          + initial_counter   = (known after apply)
          + look_ahead_window = (known after apply)
          + period            = (known after apply)
          + type              = (known after apply)
        }

      + security_defenses {
          + brute_force_detection {
              + failure_reset_time_seconds       = 43200
              + max_failure_wait_seconds         = 900
              + max_login_failures               = 30
              + minimum_quick_login_wait_seconds = 60
              + permanent_lockout                = false
              + quick_login_check_milli_seconds  = 1000
              + wait_increment_seconds           = 60
            }

          + headers {
              + content_security_policy   = "frame-src 'self'; frame-ancestors 'self'; object-src 'none';"
              + strict_transport_security = "max-age=31536000; includeSubDomains"
              + x_content_type_options    = "nosniff"
              + x_frame_options           = "DENY"
              + x_robots_tag              = "none"
              + x_xss_protection          = "1; mode=block"
            }
        }

      + smtp_server {
          + from = "keycloak@<redacted>.org"
          + host = "mail.mail.svc.cluster.local"

          + auth {}
        }

      + web_authn_passwordless_policy {
          + acceptable_aaguids                = (known after apply)
          + attestation_conveyance_preference = (known after apply)
          + authenticator_attachment          = (known after apply)
          + avoid_same_authenticator_register = (known after apply)
          + create_timeout                    = (known after apply)
          + relying_party_entity_name         = (known after apply)
          + relying_party_id                  = (known after apply)
          + require_resident_key              = (known after apply)
          + signature_algorithms              = (known after apply)
          + user_verification_requirement     = (known after apply)
        }

      + web_authn_policy {
          + attestation_conveyance_preference = "not specified"
          + authenticator_attachment          = "not specified"
          + avoid_same_authenticator_register = false
          + create_timeout                    = 0
          + relying_party_entity_name         = "<Redacted>"
          + relying_party_id                  = "keycloak.<redacted>.org"
          + require_resident_key              = "not specified"
          + signature_algorithms              = [
              + "ES256",
              + "RS256",
            ]
          + user_verification_requirement     = "not specified"
        }
    }

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

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: 
keycloak_realm.primary: Creating...

Error: Plugin did not respond

  with keycloak_realm.primary,
  on keycloak-configuration.tf line 12, in resource "keycloak_realm" "primary":
  12: resource "keycloak_realm" "primary" {

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_v3.10.0 plugin:

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

goroutine 52 [running]:
github.com/mrparkers/terraform-provider-keycloak/provider.getRealmFromData(0xc0000f9100, 0x0, 0x0, 0x0)
	github.com/mrparkers/terraform-provider-keycloak/provider/resource_keycloak_realm.go:776 +0x4a73
github.com/mrparkers/terraform-provider-keycloak/provider.resourceKeycloakRealmCreate(0xfa2ec8, 0xc0006345a0, 0xc0000f9100, 0xe757a0, 0xc000380480, 0xc000737e10, 0x616d65686373, 0xc0000f8e00)
	github.com/mrparkers/terraform-provider-keycloak/provider/resource_keycloak_realm.go:1361 +0x5a
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).create(0xc0003568c0, 0xfa2f00, 0xc00073c240, 0xc0000f9100, 0xe757a0, 0xc000380480, 0x0, 0x0, 0x0)
	github.com/hashicorp/terraform-plugin-sdk/v2@v2.12.0/helper/schema/resource.go:342 +0x17f
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*Resource).Apply(0xc0003568c0, 0xfa2f00, 0xc00073c240, 0xc0004d44e0, 0xc0000f8e00, 0xe757a0, 0xc000380480, 0x0, 0x0, 0x0, ...)
	github.com/hashicorp/terraform-plugin-sdk/v2@v2.12.0/helper/schema/resource.go:472 +0x79d
github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.(*GRPCProviderServer).ApplyResourceChange(0xc00011a4f8, 0xfa2e58, 0xc0004ae100, 0xc000730000, 0xe82c69, 0x12, 0x0)
	github.com/hashicorp/terraform-plugin-sdk/v2@v2.12.0/helper/schema/grpc_provider.go:1021 +0xb0f
github.com/hashicorp/terraform-plugin-go/tfprotov5/tf5server.(*server).ApplyResourceChange(0xc00041c500, 0xfa2f00, 0xc0004961b0, 0xc0001c64d0, 0x0, 0x0, 0x0)
	github.com/hashicorp/terraform-plugin-go@v0.8.0/tfprotov5/tf5server/server.go:812 +0x73c
github.com/hashicorp/terraform-plugin-go/tfprotov5/internal/tfplugin5._Provider_ApplyResourceChange_Handler(0xe3d4e0, 0xc00041c500, 0xfa2f00, 0xc0004961b0, 0xc000114540, 0x0, 0xfa2f00, 0xc0004961b0, 0xc0001d1500, 0x13a8)
	github.com/hashicorp/terraform-plugin-go@v0.8.0/tfprotov5/internal/tfplugin5/tfplugin5_grpc.pb.go:385 +0x214
google.golang.org/grpc.(*Server).processUnaryRPC(0xc000138540, 0xfaa438, 0xc00048c1a0, 0xc0004a0000, 0xc00028d950, 0x14834c0, 0x0, 0x0, 0x0)
	google.golang.org/grpc@v1.45.0/server.go:1282 +0x52b
google.golang.org/grpc.(*Server).handleStream(0xc000138540, 0xfaa438, 0xc00048c1a0, 0xc0004a0000, 0x0)
	google.golang.org/grpc@v1.45.0/server.go:1619 +0xd0c
google.golang.org/grpc.(*Server).serveStreams.func1.2(0xc00017e2a0, 0xc000138540, 0xfaa438, 0xc00048c1a0, 0xc0004a0000)
	google.golang.org/grpc@v1.45.0/server.go:921 +0xab
created by google.golang.org/grpc.(*Server).serveStreams.func1
	google.golang.org/grpc@v1.45.0/server.go:919 +0x1fd

Error: The terraform-provider-keycloak_v3.10.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.

Source

# configuration.tf

data "keycloak_realm" "master" {
  realm = "master"
}

variable "primary_realm" {
  type = object({
    id   = string
    name = string
  })
}

resource "keycloak_realm" "primary" {
  realm             = var.primary_realm.id
  enabled           = true
  display_name      = var.primary_realm.name
  display_name_html = "<b>${var.primary_realm.name}</b>"

  login_theme = "base"

  ssl_required    = "all"
  password_policy = "length(16) and notUsername"

  user_managed_access      = true
  reset_password_allowed   = true
  verify_email             = true
  login_with_email_allowed = true

  smtp_server {
    host = local.email.smtp.host
    from = format(local.email.pattern.from, "keycloak")

    auth {
      username = local.email.smtp.username
      password = local.email.smtp.password
    }
  }

  internationalization {
    supported_locales = ["en"]
    default_locale    = "en"
  }

  security_defenses {
    headers {
      x_frame_options                     = "DENY"
      content_security_policy             = "frame-src 'self'; frame-ancestors 'self'; object-src 'none';"
      content_security_policy_report_only = ""
      x_content_type_options              = "nosniff"
      x_robots_tag                        = "none"
      x_xss_protection                    = "1; mode=block"
      strict_transport_security           = "max-age=31536000; includeSubDomains"
    }
    brute_force_detection {
      permanent_lockout                = false
      max_login_failures               = 30
      wait_increment_seconds           = 60
      quick_login_check_milli_seconds  = 1000
      minimum_quick_login_wait_seconds = 60
      max_failure_wait_seconds         = 900
      failure_reset_time_seconds       = 43200
    }
  }

  web_authn_policy {
    relying_party_entity_name = var.primary_realm.name
    relying_party_id          = one(local.keycloak_fqdns)
    signature_algorithms      = ["ES256", "RS256"]
  }
}
@alexander-bauer
Copy link
Author

alexander-bauer commented Sep 20, 2022

Thanks to some classic binary-search-by-hand debugging, I determined that the issue occurs when the smtp's auth block is present, but not otherwise. Notably, in my case, SMTP username and email are blank.

Omitting this configuration solves this for me, but could be an issue for someone who may not know ahead of time that SMTP uses blank credentials (or needs to unset existing credentials).

@alexander-bauer alexander-bauer changed the title Plugin crash configuring realm Blank SMTP "auth" username and password cause plugin crash while configuring realm Sep 20, 2022
@mrparkers
Copy link
Contributor

Hi @alexander-bauer, I'm sorry that you've ran into this issue.

Unfortunately, this is a known issue that's caused by a bug within the terraform-plugin-sdk, for which I've opened an issue here: hashicorp/terraform-plugin-sdk#216

This was originally reported in #535, in which I provided a workaround that you might be able to use.

This may eventually be fixed when the terraform-plugin-framework becomes stable and I have the bandwidth to update this provider to use that. Until then, your best bet is probably the workaround mentioned in #535.

I'm going to close this since there's nothing I can do at the moment to fix it. Feel free to re-open or respond if you have any additional questions. Thanks!

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

No branches or pull requests

2 participants