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

Adding custom cognito user pool attribute forces new resource #3891

Closed
jayanderson opened this issue Mar 22, 2018 · 52 comments · Fixed by #18512
Closed

Adding custom cognito user pool attribute forces new resource #3891

jayanderson opened this issue Mar 22, 2018 · 52 comments · Fixed by #18512
Labels
enhancement Requests to existing resources that expand the functionality or scope.
Milestone

Comments

@jayanderson
Copy link

Adding new custom attributes should not force re-creation of the cognito user pool.

Terraform Version

$ terraform -v
Terraform v0.11.4
+ provider.aws v1.11.0

Affected Resource(s)

aws_cognito_user_pool

Terraform Configuration Files

variable "region" {
  default = "us-east-1"
}

provider "aws" {
  region = "${var.region}"
}

resource "aws_cognito_user_pool" "pool" {
  name = "bug-test-pool"

  /*
  schema {
    attribute_data_type      = "Number"
    developer_only_attribute = false
    mutable                  = false
    name                     = "custom-attribute"
    required                 = false
  }
  */
}

Debug Output

Output of running terraform plan after adding the custom attribute above.

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_cognito_user_pool.pool: Refreshing state... (ID: us-east-1_Cj77gRCdj)

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

-/+ aws_cognito_user_pool.pool (new resource required)
      id:                                               "us-east-1_Cj77gRCdj" => <computed> (forces new resource)
      admin_create_user_config.#:                       "1" => <computed>
      arn:                                              "arn:aws:cognito-idp:us-east-1:326947223243:userpool/us-east-1_Cj77gRCdj" => <computed>
      creation_date:                                    "2018-03-22T19:06:44Z" => <computed>
      email_verification_message:                       "" => <computed>
      email_verification_subject:                       "" => <computed>
      lambda_config.#:                                  "0" => <computed>
      last_modified_date:                               "2018-03-22T19:06:44Z" => <computed>
      mfa_configuration:                                "OFF" => "OFF"
      name:                                             "bug-test-pool" => "bug-test-pool"
      password_policy.#:                                "1" => <computed>
      schema.#:                                         "" => "1" (forces new resource)
      schema.2616754751.attribute_data_type:            "" => "Number"
      schema.2616754751.developer_only_attribute:       "" => "false"
      schema.2616754751.mutable:                        "" => "false"
      schema.2616754751.name:                           "" => "custom-attribute"
      schema.2616754751.number_attribute_constraints.#: "" => "0"
      schema.2616754751.required:                       "" => "false"
      schema.2616754751.string_attribute_constraints.#: "" => "0"
      verification_message_template.#:                  "1" => <computed>


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

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Panic Output

None

Expected Behavior

Add the attribute without destroying and rebuilding the cognito user pool. This is supported through the cognito UI and API (https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AddCustomAttributes.html).

Actual Behavior

The cognito user pool was rebuilt.

schema.#: "" => "1" (forces new resource)

Steps to Reproduce

  1. terraform apply - Create new user pool
  2. Add a new custom attribute
  3. terrform plan - viewing the output shows that it would re-build the cognito user pool.

Important Factoids

None

References

None

@bflad bflad added enhancement Requests to existing resources that expand the functionality or scope. service/cognito labels Mar 22, 2018
@Puneeth-n
Copy link
Contributor

I am not sure how the deletion of custom attributes work as AWS doesn't seem to support deletion of custom attributes or updating custom attributes.

@Puneeth-n
Copy link
Contributor

Puneeth-n commented Mar 23, 2018

As suspected, One cannot update or delete custom attributes once created as part of the user_pool. So the current behavior is the only way out I think 🤔 Further details in the AWS documentation

@jayanderson
Copy link
Author

Right, once the attributes are added they cannot be removed. However you can add new attributes.

@DavidRowe-SL
Copy link

DavidRowe-SL commented Mar 30, 2018

Is there a workaround for adding new attributes via terraform without having to re-create the entire user pool? Seems like it'll be tricky to add a new attribute in the future when the application is live.

Edit: Looks like pegging the version to 1.12 fixed this for us.

@bflad
Copy link
Contributor

bflad commented Mar 30, 2018

In the meantime, you can do it outside Terraform (web console, CLI, etc.) and just sync your Terraform configuration afterwards.

@leonfs
Copy link

leonfs commented Apr 10, 2018

Doing a bit more research. I've found the problem. If the schema attribute (in my case String) does not include the string_attribute_constraints it will force a new resource every time.

The following generates a new resource each time:

schema {
    attribute_data_type      = "String"
    developer_only_attribute = false
    mutable                  = false
    name                     = "picture"
    required                 = true
  }

While this does not:

schema {
    attribute_data_type      = "String"
    developer_only_attribute = false
    mutable                  = false
    name                     = "picture"
    required                 = true

    string_attribute_constraints {
      min_length = 6
      max_length = 32
    }
  }

Most likely it's a different bug.

@Puneeth-n
Copy link
Contributor

@leonfs I think we need a customizediff function here. that evaluates thwbrules for when the pool has to be recreated and when it should be modified. @bflad Can you please confirm what needs to be done and I can pick this up.

@leonfs
Copy link

leonfs commented Apr 17, 2018

@Puneeth-n Yes - seems like that will be the case. At the moment there is a ForceNew: true on the schema set, but that is clearly not the case with custom attributes.

I've referenced (see above) another issue I encountered after I added an identity provider (Google) to the user Pool.

Looks like AWS adds a custom attribute called identities after adding a provider, making the schema's set to change and forcing a whole new pool to be recreated. You can see that I provided a short term solution to it but only works if you know before hand (resource creation) that you will use identity providers.

@pankajku
Copy link

Looks like terraform forces a destroy and create of a user pool even if nothing changed in the .tf file.

$ cat main.tf

provider "aws" {
}

resource "aws_cognito_user_pool" "pankajk_security" {
  name                       = "pankajk-security"
  email_verification_subject = "Your Verification Code"
  email_verification_message = "Please use the following code: {####}"
  alias_attributes           = ["email", "preferred_username"]
  auto_verified_attributes   = ["email"]

  verification_message_template {
    default_email_option = "CONFIRM_WITH_CODE"
  }

  password_policy {
    minimum_length    = 10
    require_lowercase = true
    require_numbers   = true
    require_symbols   = true
    require_uppercase = true
  }

  schema {
    attribute_data_type      = "String"
    developer_only_attribute = false
    mutable                  = true
    name                     = "email"
    required                 = true

    string_attribute_constraints {
      min_length = 7
      max_length = 256
    }
  }

  schema {
    attribute_data_type      = "String"
    developer_only_attribute = false
    mutable                  = true
    name                     = "oid"
    required                 = false

    number_attribute_constraints {
      min_value = 1
      max_value = 256
    }
  }
}

$ terraform -v

Terraform v0.11.7
+ provider.aws v1.14.1

$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + aws_cognito_user_pool.pankajk_security
      id:                                                          <computed>
      admin_create_user_config.#:                                  <computed>
      alias_attributes.#:                                          "2"
      alias_attributes.1888159429:                                 "preferred_username"
      alias_attributes.881205744:                                  "email"
      arn:                                                         <computed>
      auto_verified_attributes.#:                                  "1"
      auto_verified_attributes.881205744:                          "email"
      creation_date:                                               <computed>
      email_verification_message:                                  "Please use the following code: {####}"
      email_verification_subject:                                  "Your Verification Code"
      lambda_config.#:                                             <computed>
      last_modified_date:                                          <computed>
      mfa_configuration:                                           "OFF"
      name:                                                        "pankajk-security"
      password_policy.#:                                           "1"
      password_policy.0.minimum_length:                            "10"
      password_policy.0.require_lowercase:                         "true"
      password_policy.0.require_numbers:                           "true"
      password_policy.0.require_symbols:                           "true"
      password_policy.0.require_uppercase:                         "true"
      schema.#:                                                    "2"
      schema.1734507539.attribute_data_type:                       "String"
      schema.1734507539.developer_only_attribute:                  "false"
      schema.1734507539.mutable:                                   "true"
      schema.1734507539.name:                                      "email"
      schema.1734507539.number_attribute_constraints.#:            "0"
      schema.1734507539.required:                                  "true"
      schema.1734507539.string_attribute_constraints.#:            "1"
      schema.1734507539.string_attribute_constraints.0.max_length: "256"
      schema.1734507539.string_attribute_constraints.0.min_length: "7"
      schema.3768180960.attribute_data_type:                       "String"
      schema.3768180960.developer_only_attribute:                  "false"
      schema.3768180960.mutable:                                   "true"
      schema.3768180960.name:                                      "oid"
      schema.3768180960.number_attribute_constraints.#:            "1"
      schema.3768180960.number_attribute_constraints.0.max_value:  "256"
      schema.3768180960.number_attribute_constraints.0.min_value:  "1"
      schema.3768180960.required:                                  "false"
      schema.3768180960.string_attribute_constraints.#:            "0"
      verification_message_template.#:                             "1"
      verification_message_template.0.default_email_option:        "CONFIRM_WITH_CODE"
      verification_message_template.0.email_message:               <computed>
      verification_message_template.0.email_message_by_link:       <computed>
      verification_message_template.0.email_subject:               <computed>
      verification_message_template.0.email_subject_by_link:       <computed>
      verification_message_template.0.sms_message:                 <computed>


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: yes

aws_cognito_user_pool.pankajk_security: Creating...
  admin_create_user_config.#:                                  "" => "<computed>"
  alias_attributes.#:                                          "" => "2"
  alias_attributes.1888159429:                                 "" => "preferred_username"
  alias_attributes.881205744:                                  "" => "email"
  arn:                                                         "" => "<computed>"
  auto_verified_attributes.#:                                  "" => "1"
  auto_verified_attributes.881205744:                          "" => "email"
  creation_date:                                               "" => "<computed>"
  email_verification_message:                                  "" => "Please use the following code: {####}"
  email_verification_subject:                                  "" => "Your Verification Code"
  lambda_config.#:                                             "" => "<computed>"
  last_modified_date:                                          "" => "<computed>"
  mfa_configuration:                                           "" => "OFF"
  name:                                                        "" => "pankajk-security"
  password_policy.#:                                           "" => "1"
  password_policy.0.minimum_length:                            "" => "10"
  password_policy.0.require_lowercase:                         "" => "true"
  password_policy.0.require_numbers:                           "" => "true"
  password_policy.0.require_symbols:                           "" => "true"
  password_policy.0.require_uppercase:                         "" => "true"
  schema.#:                                                    "" => "2"
  schema.1734507539.attribute_data_type:                       "" => "String"
  schema.1734507539.developer_only_attribute:                  "" => "false"
  schema.1734507539.mutable:                                   "" => "true"
  schema.1734507539.name:                                      "" => "email"
  schema.1734507539.number_attribute_constraints.#:            "" => "0"
  schema.1734507539.required:                                  "" => "true"
  schema.1734507539.string_attribute_constraints.#:            "" => "1"
  schema.1734507539.string_attribute_constraints.0.max_length: "" => "256"
  schema.1734507539.string_attribute_constraints.0.min_length: "" => "7"
  schema.3768180960.attribute_data_type:                       "" => "String"
  schema.3768180960.developer_only_attribute:                  "" => "false"
  schema.3768180960.mutable:                                   "" => "true"
  schema.3768180960.name:                                      "" => "oid"
  schema.3768180960.number_attribute_constraints.#:            "" => "1"
  schema.3768180960.number_attribute_constraints.0.max_value:  "" => "256"
  schema.3768180960.number_attribute_constraints.0.min_value:  "" => "1"
  schema.3768180960.required:                                  "" => "false"
  schema.3768180960.string_attribute_constraints.#:            "" => "0"
  verification_message_template.#:                             "" => "1"
  verification_message_template.0.default_email_option:        "" => "CONFIRM_WITH_CODE"
  verification_message_template.0.email_message:               "" => "<computed>"
  verification_message_template.0.email_message_by_link:       "" => "<computed>"
  verification_message_template.0.email_subject:               "" => "<computed>"
  verification_message_template.0.email_subject_by_link:       "" => "<computed>"
  verification_message_template.0.sms_message:                 "" => "<computed>"
aws_cognito_user_pool.pankajk_security: Creation complete after 3s (ID: us-west-2_t6jMrbPx1)

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

$terraform plan

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_cognito_user_pool.pankajk_security: Refreshing state... (ID: us-west-2_t6jMrbPx1)

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

-/+ aws_cognito_user_pool.pankajk_security (new resource required)
      id:                                                          "us-west-2_t6jMrbPx1" => <computed> (forces new resource)
      admin_create_user_config.#:                                  "1" => <computed>
      alias_attributes.#:                                          "2" => "2"
      alias_attributes.1888159429:                                 "preferred_username" => "preferred_username"
      alias_attributes.881205744:                                  "email" => "email"
      arn:                                                         "arn:aws:cognito-idp:us-west-2:166326852216:userpool/us-west-2_t6jMrbPx1" => <computed>
      auto_verified_attributes.#:                                  "1" => "1"
      auto_verified_attributes.881205744:                          "email" => "email"
      creation_date:                                               "2018-04-18T18:11:08Z" => <computed>
      email_verification_message:                                  "Please use the following code: {####}" => "Please use the following code: {####}"
      email_verification_subject:                                  "Your Verification Code" => "Your Verification Code"
      lambda_config.#:                                             "0" => <computed>
      last_modified_date:                                          "2018-04-18T18:11:08Z" => <computed>
      mfa_configuration:                                           "OFF" => "OFF"
      name:                                                        "pankajk-security" => "pankajk-security"
      password_policy.#:                                           "1" => "1"
      password_policy.0.minimum_length:                            "10" => "10"
      password_policy.0.require_lowercase:                         "true" => "true"
      password_policy.0.require_numbers:                           "true" => "true"
      password_policy.0.require_symbols:                           "true" => "true"
      password_policy.0.require_uppercase:                         "true" => "true"
      schema.#:                                                    "2" => "2"
      schema.1734507539.attribute_data_type:                       "String" => "String"
      schema.1734507539.developer_only_attribute:                  "false" => "false"
      schema.1734507539.mutable:                                   "true" => "true"
      schema.1734507539.name:                                      "email" => "email"
      schema.1734507539.number_attribute_constraints.#:            "0" => "0"
      schema.1734507539.required:                                  "true" => "true"
      schema.1734507539.string_attribute_constraints.#:            "1" => "1"
      schema.1734507539.string_attribute_constraints.0.max_length: "256" => "256"
      schema.1734507539.string_attribute_constraints.0.min_length: "7" => "7"
      schema.3768180960.attribute_data_type:                       "" => "String" (forces new resource)
      schema.3768180960.developer_only_attribute:                  "" => "false" (forces new resource)
      schema.3768180960.mutable:                                   "" => "true" (forces new resource)
      schema.3768180960.name:                                      "" => "oid" (forces new resource)
      schema.3768180960.number_attribute_constraints.#:            "" => "1" (forces new resource)
      schema.3768180960.number_attribute_constraints.0.max_value:  "" => "256" (forces new resource)
      schema.3768180960.number_attribute_constraints.0.min_value:  "" => "1" (forces new resource)
      schema.3768180960.required:                                  "" => "false" (forces new resource)
      schema.3768180960.string_attribute_constraints.#:            "" => "0"
      schema.383977790.attribute_data_type:                        "String" => "" (forces new resource)
      schema.383977790.developer_only_attribute:                   "false" => "false"
      schema.383977790.mutable:                                    "true" => "false" (forces new resource)
      schema.383977790.name:                                       "oid" => "" (forces new resource)
      schema.383977790.number_attribute_constraints.#:             "0" => "0"
      schema.383977790.required:                                   "false" => "false"
      schema.383977790.string_attribute_constraints.#:             "1" => "0" (forces new resource)
      schema.383977790.string_attribute_constraints.0.max_length:  "" => ""
      schema.383977790.string_attribute_constraints.0.min_length:  "" => ""
      verification_message_template.#:                             "1" => "1"
      verification_message_template.0.default_email_option:        "CONFIRM_WITH_CODE" => "CONFIRM_WITH_CODE"
      verification_message_template.0.email_message:               "Please use the following code: {####}" => <computed>
      verification_message_template.0.email_message_by_link:       "" => <computed>
      verification_message_template.0.email_subject:               "Your Verification Code" => <computed>
      verification_message_template.0.email_subject_by_link:       "" => <computed>
      verification_message_template.0.sms_message:                 "" => <computed>


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

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

@Puneeth-n
Copy link
Contributor

@pankajku The issue you are facing is different. However, IMHO terraform should be able to catch such errors.

There is an error in your config. For oid, you specify attribute_data_type = "String" but specify number_attribute_constraints The corrected config is below:

variable "region" {
  default = "us-east-1"
}

provider "aws" {
  version               = "1.14.1"
  region                = "${var.region}"
}

resource "aws_cognito_user_pool" "pankajk_security" {
  name                       = "pankajk-security"
  email_verification_subject = "Your Verification Code"
  email_verification_message = "Please use the following code: {####}"
  alias_attributes           = ["email", "preferred_username"]
  auto_verified_attributes   = ["email"]

  verification_message_template {
    default_email_option = "CONFIRM_WITH_CODE"
  }

  password_policy {
    minimum_length    = 10
    require_lowercase = true
    require_numbers   = true
    require_symbols   = true
    require_uppercase = true
  }

  schema {
    attribute_data_type      = "String"
    developer_only_attribute = false
    mutable                  = true
    name                     = "email"
    required                 = true

    string_attribute_constraints {
      min_length = 7
      max_length = 256
    }
  }

  schema {
    attribute_data_type      = "String"
    developer_only_attribute = false
    mutable                  = true
    name                     = "oid"
    required                 = false

    string_attribute_constraints {
      min_length = 1
      max_length = 256
    }
  }
}

@pankajku
Copy link

@Puneeth-n , Thanks for catching the problem in my config. I changed it as per your suggestion and now terraform updates only the changed attributes.

I did notice that after I make a simple change (such as verification message text) in config file and run "terraform apply", the email verification flag gets unset.

$ terraform apply

aws_cognito_user_pool.pankajk_security: Refreshing state... (ID: us-west-2_LKVhvfWsH)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  ~ aws_cognito_user_pool.pankajk_security
      email_verification_subject: "Your verification code" => "Your Verification Code"


Plan: 0 to add, 1 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: yes

aws_cognito_user_pool.pankajk_security: Modifying... (ID: us-west-2_LKVhvfWsH)
  email_verification_subject: "Your verification code" => "Your Verification Code"
aws_cognito_user_pool.pankajk_security: Modifications complete after 1s (ID: us-west-2_LKVhvfWsH)

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

$ terraform plan

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_cognito_user_pool.pankajk_security: Refreshing state... (ID: us-west-2_LKVhvfWsH)

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  ~ aws_cognito_user_pool.pankajk_security
      auto_verified_attributes.#:         "0" => "1"
      auto_verified_attributes.881205744: "" => "email"


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

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Wonder if this is also due to some error in the config file or a bug.

@ravenscar
Copy link

This still seems to be a problem and is going to cause someone a lot of heartache one day when tf drops the user pool and they lose all their users...

Adding this to the schema causes the user pool to be destroyed, despite being able to be created in the console/cli without destroying.

    {
      name                     = "foo"
      attribute_data_type      = "String"
      mutable                  = true
      developer_only_attribute = "false"
      required                 = "false"

      string_attribute_constraints = {
        min_length = 0
        max_length = 256
      }
    },

@Puneeth-n
Copy link
Contributor

Yea. I have prevent_destroy set on both the pool and client

@Lezeper
Copy link

Lezeper commented Sep 19, 2018

Still hitting the resource recreate issue when I try to add new custom attributes.

Terraform Version
Terraform v0.11.8
provider.aws v1.36.0

Before adding new custom attribute

resource "aws_cognito_user_pool" "pool" {
  name                       = "Test"
  username_attributes        = ["email"]
  auto_verified_attributes   = ["email"]

  schema = [
    {
      attribute_data_type          = "String"
      developer_only_attribute     = false
      mutable                      = false
      name                         = "email"
      required                     = true
      string_attribute_constraints = {
        min_length = 1
        max_length = 256
      }
    },
    {
      attribute_data_type          = "String"
      developer_only_attribute     = false
      mutable                      = true
      name                         = "custom1"
      required                     = false
      string_attribute_constraints = {
        min_length = 0
        max_length = 256
      }
    }
  ]
}

Add new custom attribute

{
      attribute_data_type          = "String"
      developer_only_attribute     = false
      mutable                      = true
      name                         = "custom2"
      required                     = false
      string_attribute_constraints = {
        min_length = 0
        max_length = 256
      }
    }

Debug Ouput

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

-/+ aws_cognito_user_pool.pool (new resource required)
 ...
      lambda_config.#:                                             "0" => <computed>
      last_modified_date:                                          "2018-09-19T03:33:52Z" => <computed>
      mfa_configuration:                                           "OFF" => "OFF"
      name:                                                        "Test" => "Test"
      password_policy.#:                                           "1" => <computed>
      schema.#:                                                    "2" => "3" (forces new resource)
      schema.2766842814.attribute_data_type:                       "" => "String" (forces new resource)
      schema.2766842814.developer_only_attribute:                  "" => "false" (forces new resource)
      schema.2766842814.mutable:                                   "" => "true" (forces new resource)
      schema.2766842814.name:                                      "" => "custom2" (forces new resource)
      schema.2766842814.number_attribute_constraints.#:            "" => "0"
      schema.2766842814.required:                                  "" => "false" (forces new resource)
      schema.2766842814.string_attribute_constraints.#:            "" => "1" (forces new resource)
      schema.2766842814.string_attribute_constraints.0.max_length: "" => "256" (forces new resource)
      schema.2766842814.string_attribute_constraints.0.min_length: "" => "0" (forces new resource)
      schema.3686385984.attribute_data_type:                       "String" => "String"
      schema.3686385984.developer_only_attribute:                  "false" => "false"
      schema.3686385984.mutable:                                   "false" => "false"
      schema.3686385984.name:                                      "email" => "email"
      schema.3686385984.number_attribute_constraints.#:            "0" => "0"
      schema.3686385984.required:                                  "true" => "true"
      schema.3686385984.string_attribute_constraints.#:            "1" => "1"
      schema.3686385984.string_attribute_constraints.0.max_length: "256" => "256"
      schema.3686385984.string_attribute_constraints.0.min_length: "1" => "1"
      schema.893709367.attribute_data_type:                        "String" => "String"
      schema.893709367.developer_only_attribute:                   "false" => "false"
      schema.893709367.mutable:                                    "true" => "true"
      schema.893709367.name:                                       "custom1" => "custom1"
      schema.893709367.number_attribute_constraints.#:             "0" => "0"
      schema.893709367.required:                                   "false" => "false"
      schema.893709367.string_attribute_constraints.#:             "1" => "1"
      schema.893709367.string_attribute_constraints.0.max_length:  "256" => "256"
      schema.893709367.string_attribute_constraints.0.min_length:  "0" => "0"
      username_attributes.#:                                       "1" => "1"
      username_attributes.0:                                       "email" => "email"
      verification_message_template.#:                             "1" => <computed>


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

@kanemotos
Copy link

FYI: I made custom attribute without string_attribute_constraints, then I faced same bug.

  schema {
    name                     = "custom_id"
    required                 = false
    attribute_data_type      = "String"
    developer_only_attribute = false
    mutable                  = true
  }

After I added empty string_attribute_constraints, I could avoid this bug!

  schema {
    name                     = "custom_id"
    required                 = false
    attribute_data_type      = "String"
    developer_only_attribute = false
    mutable                  = true

    string_attribute_constraints {}
  }

I really appreciate everyone's workaround!

@ghost
Copy link

ghost commented Dec 20, 2018

Workaround doesn't work for me.

schema {
    attribute_data_type      = "String"
    developer_only_attribute = false
    mutable                  = true
    name                     = "parent_id"
    required                 = false

    string_attribute_constraints {
      min_length = 1
      max_length = 256
    }
  }

Plan:

schema.#:                                                    "10" => "11" (forces new resource)
schema.2272806367.attribute_data_type:                       "" => "String" (forces new resource)
schema.2272806367.developer_only_attribute:                  "" => "false" (forces new resource)
schema.2272806367.mutable:                                   "" => "false" (forces new resource)
schema.2272806367.name:                                      "" => "parent_id" (forces new resource)
schema.2272806367.number_attribute_constraints.#:            "" => "0"
schema.2272806367.required:                                  "" => "false" (forces new resource)
schema.2272806367.string_attribute_constraints.#:            "" => "1" (forces new resource)
schema.2272806367.string_attribute_constraints.0.max_length: "" => "256" (forces new resource)
schema.2272806367.string_attribute_constraints.0.min_length: "" => "1" (forces new resource)

Versions:

Terraform v0.11.11
+ provider.archive v1.1.0
+ provider.aws v1.52.0

This is a huge issue for anyone who is developing new applications and require to add/experiment with custom attributes. We had our pool destroyed 10+ times because of this.

@dguisinger
Copy link

Any progress on this? You guys are forcing us to blow away a resource that involves asking the customer to reset their passwords (assuming we even have backup data to import in the first place), or for me, I setup a lifecycle ignore_changes * and hope someone finally gets around to fixing this before I need another change.

The fact this has been sitting out there for 9 months is seriously making me wonder whether I should trust critical infrastructure to Terraform.

@dnagir
Copy link

dnagir commented Dec 30, 2018

The workaround doesn't work for me either. It always recreates the pool even if there are no changes to the templates.

> terraform --version
Terraform v0.11.11
+ provider.archive v1.1.0
+ provider.aws v1.54.0

@juliedavila
Copy link

still an isssue

Terraform v0.11.11
+ provider.aws v1.57.0

@lqueryvg
Copy link

And still...

Terraform v0.11.11
+ provider.aws v1.59.0

@ligustah
Copy link

ligustah commented Mar 1, 2019

I'm also affected by this, none of the workarounds have worked for me.

Terraform v0.11.11
+ provider.aws v1.60.0

@voroniys
Copy link

voroniys commented Apr 8, 2019

The fact this has been sitting out there for 9 months is seriously making me wonder whether I should trust critical infrastructure to Terraform.

I'm asking myself the same question. There are a lot of critical bugs not handled for more then a year, some - for more than two years. For a lot of these bugs there are ready PR which also hangingin unlandled for more than a year.

Also recently I have filled a bug report for a serious but in jsonencode function - they refused to fiz it. The reply was - it is fixed in version 12, which will be released some unknown time in the future and we don't care about version 11.

BTW the issue from this topic is not the only one, that cognito user pool has. Callback_urls has to be ordered exactly as AWS doing this, otherwise terraform constantly trying to change order.

@Puneeth-n
Copy link
Contributor

@voroniys My take away from using Terraform for 3+ years is not to maintain states via Terraform. It is true for any IaC. Terraform is a powerful tool and has God access. Refrain from using it for applications having state.

@alihalabyah
Copy link

Still an issue.

@bkielbasa
Copy link

ping as well. Manually managing the state is... ridiculous

@mmierzwa
Copy link

mmierzwa commented May 6, 2020

Guys, any updates? We are in 2020 now...

@larryboymi
Copy link

Yes, still an issue...

@efernandes-dev-ops
Copy link

Hope this helps everyone else, easier way than the above solution and potentially less messier than playing around with the terraform state and imports.

Similar to ePoromaa, you will need to run the aws cli cmd manually to add a custom attribute to the cognito user pool.
aws cognito-idp add-custom-attributes --user-pool-id us-west-2_aaaaaaaaa --custom-attributes Name="CustomAttr1",AttributeDataType="String",DeveloperOnlyAttribute=false,Required=false,StringAttributeConstraints="{MinLength=1,MaxLength=15}"
More info on available attributes can be found: https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/add-custom-attributes.html

Once you've added the custom attribute via the aws cli, you will now need to add the schema block for it in your terraform cognito user pool code. For example

schema { name = "CustomAttr1" attribute_data_type = "String" required = false developer_only_attribute = false string_attribute_constraints { min_length = 1 max_length = 15 } }

Once the schema block is added into terraform, terraform picks up no changes. Would consider this safe to do in prod as well.

@jorenvh1
Copy link

Terraform v0.12.26

  • provider.aws v2.56.0

Still have the issue...

@martincastrocm
Copy link

martincastrocm commented Jun 22, 2020

Hi everyone, any updates on here?

@viktornord
Copy link

Please fix this issue!

@AugustDev
Copy link

This is still an issue with

Terraform v0.12.28
+ provider.aws v2.67.0

Please address.

@maxfortun
Copy link
Contributor

Workaround to prevent destruction of the user pool:

  1. Add custom attribute via console or cli.
  2. Add schema block to terraform template IDENTICAL IN EVERY WAY to the attribute you just created.
  3. Run terraform refresh. It should refresh the state file to reflect the schema.
  4. Run terraform plan to make sure user pool is no longer destroyed.

@flexelem
Copy link

Hi there, we are also facing this issue. Any updates? Thanks!

@Chanonry
Copy link

Chanonry commented Sep 1, 2020

Anybody from HashiCorp out there ? Hellooo....

@pabloa502
Copy link

Facing this as well:

Terraform v0.12.29

@cryptoPickle
Copy link

Terraform v0.13.3

  • provider registry.terraform.io/hashicorp/aws v2.70.0

Still facing the issue

@breathingdust
Copy link
Member

Hi all! 👋 Just wanted to direct you to our public roadmap for this quarter (Nov-Jan) in which this item has been mentioned.

Due to the significant community interest in resolving this issue, we will be looking at merging existing contributions soon.

We appreciate all the contributions and feedback thus far.

@psrivastava-rsc
Copy link

psrivastava-rsc commented Dec 2, 2020

Thanks, @eporomaa and @efernandes-dev-ops This workaround worked for me. Basically, it ran the following commands

terraform state list # to figure out what is resource state for cognito in my project

terraform state rm aws_cognito_user_pool.my_pool # remove state

Now you can add new attributes via CLI or web console. We need to make sure that terraform resource file must contain those attributes you added via CLI or console. Actually, the terraform resource file should be synced with Cognito

terraform import -var "provider_role_arn=<ROLE_ARN>" aws_cognito_user_pool.my_pool <USER_POOL_ID>	

@kmajic
Copy link

kmajic commented Jan 15, 2021

Our workaround is similar to @dguisinger, except we don't ignore everything via wildcard, but only the schema changes. The problem was even when we only make changes to the load balancer or something else, Terraform would re-create the Cognito user pool, because they're in the same plan.

This code bit was inserted so that our pipeline would be able to run multiple times per day:

resource "aws_cognito_user_pool" "pool" {
  name = "${var.project-name}-${var.stage}"
  (...)
  schema {
    name                     = "email"
    attribute_data_type      = "String"
    mutable                  = true
    required                 = true
  }
  lifecycle {
    ignore_changes = [
      schema     ### AWS doesn't allow schema updates, so every build will re-create the user pool unless we ignore this bit
    ]
  }

@jessedoyle
Copy link

@breathingdust - We're nearing the end of January 2021. This is a very significant issue for anyone using terraform to manage Cognito user pools. Any updates?

@bill-rich
Copy link
Contributor

I've been looking into addressing this, but the fix is currently blocked on hashicorp/terraform-plugin-sdk#497. We need to be able to compare the two schema sets to determine if a member of the set has been added, modified, or removed and take the appropriate action. As things are now, any schema that includes a nested attribute will appear to have changed, and will force the recreation of the resource.

@bill-rich
Copy link
Contributor

After looking back at how this could be implemented, I found another potential way to solve it. I've opened a PR with the alternate method.

@github-actions github-actions bot added this to the v3.35.0 milestone Apr 1, 2021
@ghost
Copy link

ghost commented Apr 1, 2021

This has been released in version 3.35.0 of the Terraform AWS provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template for triage. Thanks!

@murand78
Copy link

murand78 commented Apr 2, 2021

Get errors when apply the tf to a UserPool created with 3.33 version of AWS Provider
Do not force recreation of the pool but try to modify attributes (that are unmutable).
..............................

      - schema {
          - attribute_data_type      = "String" -> null
          - developer_only_attribute = false -> null
          - mutable                  = true -> null
          - name                     = "name" -> null
          - required                 = true -> null

          - string_attribute_constraints {
              - max_length = "2048" -> null
              - min_length = "0" -> null
            }
        }
      + schema {
          + attribute_data_type = "String"
          + mutable             = true
          + name                = "name"
          + required            = true
        }
        
Plan: 0 to add, 1 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: yes

module.cognito.aws_cognito_user_pool._user_pool: Modifying... [id=eu-west-1_XXXXXXXXX]

Error: error updating Cognito User Pool (eu-west-1_XXXXXXXXX): cannot modify or remove schema items

@ghost
Copy link

ghost commented May 2, 2021

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

@ghost ghost locked as resolved and limited conversation to collaborators May 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement Requests to existing resources that expand the functionality or scope.
Projects
None yet