Regex for variable validation

Hello,

I am trying to write a variable validation for a password variable. The validation should validate that the password matches the complexity requirements for the password. I’ve included the variable with current validation rules below:

variable "console_password" {
  type        = string
  description = <<EOT
  (Required) The password for the firewall management console.
  EOT
  validation {
    condition = can(regex("^(?=.*[0-9])(?=.*[^A-Za-z0-9])(?=.*[a-z])(?=.*[A-Z])(?=(.*)).{10,60}$", var.console_password))
    error_message = <<EOT
    ERROR: Must be at least 10 characters. At least 1 lowercase and 1 uppercase letter. At least one numeric character. At least one special character.
    EOT
  }
}

However, when I provide a value for the variable that should match the regex pattern, I still get an error about the value not passing the validation rule.

Hi @Dev0psPleb,

Can you share the test cases you are using to represent both the valid and invalid cases? I’d like to try to reproduce what you are trying as a first step.

After some fiddling, I have it working with the following regex:

condition = can(regex("^(.*[0-9])(.*[^A-Za-z0-9])(.*[a-z])(.*[A-Z])((.*)).{10,60}$", var.console_password))

My test cases that work with the above regex are:

password_validation_test_1: "!@83lvsos4mw7f!f*aPLms9HD#TqSb"
password_validation_test_2: "@v7gG5af&*6Fz!aB@d^nVetz5ML2Y1"
password_validation_test_3: "Rj&T6Xann628^BgtTg%0pp#XVddeTE"

However, testing with something like the following doesn’t work.

password_validation_test_4: "P@ssword!1234"

I’m happy with the current validation as it ultimately requires good password complexity, however, my error message output is going to be confusing for consumers of the module as the requirements stated are:

  • At least 10 characters
  • At least one upper case letter
  • At least one lower case letter
  • At least one special character
  • At least one numerical character

Seeing your list of several independent rules here makes me think it might be better to write several rules that each test only one of these conditions, rather than trying to pack them all together into a single rule:


variable "console_password" {
  type    = string
  default = "Boop1111111111111111111111111111!"

  validation {
    condition = length(var.console_password) >= 10
    error_message = "Password must have at least 10 characters."
  }

  validation {
    condition = can(regex("[A-Z]", var.console_password))
    error_message = "Password must contain at least one uppercase letter."
  }

  validation {
    condition = can(regex("[a-z]", var.console_password))
    error_message = "Password must contain at least one lowercase letter."
  }

  validation {
    condition = can(regex("[^a-zA-Z0-9]", var.console_password))
    error_message = "Password must contain at least one character that isn't a letter or a digit."
  }

  validation {
    condition = can(regex("[0-9]", var.console_password))
    error_message = "Password must contain at least one digit."
  }
}

This means that if someone provides a password that violates only one of the rules they will only see the error message for that case. But conversely it means that if they violate many of the rules then Terraform will report many separate error messages, which is quite verbose:

β•·
β”‚ Error: Invalid value for variable
β”‚ 
β”‚   on password-validation.tf line 2:
β”‚    2: variable "console_password" {
β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     β”‚ var.console_password is "beep"
β”‚ 
β”‚ Password must have at least 10 characters.
β”‚ 
β”‚ This was checked by the validation rule at password-validation.tf:6,3-13.
β•΅
β•·
β”‚ Error: Invalid value for variable
β”‚ 
β”‚   on password-validation.tf line 2:
β”‚    2: variable "console_password" {
β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     β”‚ var.console_password is "beep"
β”‚ 
β”‚ Password must contain at least one uppercase letter.
β”‚ 
β”‚ This was checked by the validation rule at password-validation.tf:11,3-13.
β•΅
β•·
β”‚ Error: Invalid value for variable
β”‚ 
β”‚   on password-validation.tf line 2:
β”‚    2: variable "console_password" {
β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     β”‚ var.console_password is "beep"
β”‚ 
β”‚ Password must contain at least one character that isn't a letter or a digit.
β”‚ 
β”‚ This was checked by the validation rule at password-validation.tf:21,3-13.
β•΅
β•·
β”‚ Error: Invalid value for variable
β”‚ 
β”‚   on password-validation.tf line 2:
β”‚    2: variable "console_password" {
β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     β”‚ var.console_password is "beep"
β”‚ 
β”‚ Password must contain at least one digit.
β”‚ 
β”‚ This was checked by the validation rule at password-validation.tf:26,3-13.
β•΅

On the plus side, this one does seem to accept your previously-failing case "P@ssword!1234".

1 Like