CiscoDevNet/terraform-provider-iosxe

iosxe_username cannot update user informations

Opened this issue · 2 comments

iosxe_username is not able to update the remote user. (Also, the "description" variable does not work)

Steps to reproduce

Define the provider and a new user:

provider "iosxe" {
  alias = "test"
  devices = [
    {
      name = "test"
      url  = "https://10.11.12.13"
    },
  ]
}

resource "iosxe_username" "test_user" {
  provider = iosxe.test

  name      = "test_user"
  privilege = 15
  # description         = ""  # Description is not supported
  secret            = "mysuperpassword"
}

Now change the secret value, e.g.:

...

resource "iosxe_username" "test_user" {
  provider = iosxe.test

  name      = "test_user"
  privilege = 15
  secret            = "my_NEW_superpassword"  # <----------------------------------------------------
}

If I run terraform with TF_LOG=DEBUG terraform apply -auto-approve, I will see:

2024/02/21 10:45:20 [DEBUG] HTTP Request: PATCH, https://10.11.12.13/restconf/data/Cisco-IOS-XE-native:native/username, {{"Cisco-IOS-XE-native:username":{"name":"test_user","privilege":"15","secret":{"secret":"my_NEW_superpassword"}}}}
2024/02/21 10:45:22 [DEBUG] HTTP Response: {
  "errors": {
    "error": [
      {
        "error-message": "inconsistent value: Device refused one or more commands",
        "error-path": "/Cisco-IOS-XE-native:native/username",
        "error-tag": "invalid-value",
        "error-type": "application"
      }
    ]
  }
}

Workaround

We can force to replace the user instead of updating him using lifecycle:replace_triggered_by and lifecycle:ignore_changes meta-arguments but this is still not optimal

locals {
    username = "test_user"
}

resource "null_resource" "local_admin_replace_trigger" {
  triggers = {
    username = local.username
    password = module.password.result
  }
}

resource "iosxe_username" "test_user" {
  provider = iosxe.test

  name      =  local.username
  privilege = 15
  secret            = "mysuperpassword"  
  lifecycle {
    ignore_changes = all
    replace_triggered_by = [      # <----------------------------------------------------
      aws_secretsmanager_secret_version.this.secret_string
    ]
  }
}

Especially, replace_triggered_by meta-argument only allows resources/count/each sources, meaning we cannot use a variable inside of it. ignore_changes is required because, with state refreshing, the secret on the device is not the same as provided unencrypted because the value; the value in the configuration is not encrypted, while the value on the remote is. This means that, even if the secret does not change, terraform will think there is a change

NOTE: In this workaround, I first only used the password as a trigger, but for an unknown reason, terraform always think that the username changed as well, therefore I also must ensure that the username triggers a replacement

Cisco version

Nb: This bug was confirmed with one specific version, but it may also impact others

#show version
Cisco IOS XE Software, Version 16.12.07
Cisco IOS Software [Gibraltar], Catalyst L3 Switch Software (CAT3K_CAA-UNIVERSALK9-M), Version 16.12.7, RELEASE SOFTWARE (fc2)

Additional information

  • The first creation of the user work even if the user already exists on the device prior to terraform execution. I therefore think there is an issue with the "PATCH" requrest

Hi @danischm, I saw that you are the most active contributor and that you approved PR.
I am wondering if you could confirm this issue and if there are any plan on fixing it ?

Nb: If needed, I may contribute.
Thank you for your response

I need to further investigate this..