jfrog/terraform-provider-artifactory

Broken group update for artifactory_user resource

Closed this issue · 3 comments

Hi,

we have detected an issue that prevents user groups are updated. However, while reproducing/minimizing the issue we stumbled over some more -- related and unrelated -- issues which causes this ticket to likely become more elaborate. Still, our main intention is the ability to update groups of existing users.

Reproduction / Description

Short Version (not comprehensive)

Step 1: Create User

resource "artifactory_user" "test_user" {
  name                       = "max_power"
  email                      = "max.power@test.invalid"
  admin                      = false
  profile_updatable          = true
  disable_ui_access          = false
  internal_password_disabled = false
  groups                     = []
}

Step 2: Add to group

resource "artifactory_user" "test_user" {
  name                       = "max_power"
  email                      = "max.power@test.invalid"
  admin                      = false
  profile_updatable          = true
  disable_ui_access          = false
  internal_password_disabled = false
  groups                     = [artifactory_group.test_group.name]
}



resource "artifactory_group" "test_group" {
  name             = "temp-test"
  description      = "temp-test"
  admin_privileges = false
  lifecycle {
    ignore_changes = [users_names]
  }
}

Result

╷
│ Error: Unable to Update Resource
│ 
│   with artifactory_user.test_user,
│   on example.tf line 3, in resource "artifactory_user" "test_user":
│    3: resource "artifactory_user" "test_user" {
│ 
│ An unexpected error occurred while updating the resource update request. Please report this issue to the provider developers.
│ 
│ Error: BAD_REQUEST - Cannot create a user without a password

The BAD_REQUEST error stems from the access/api/v2/users/{name} endpoint of the Artifactory API. As a result, we are not able to add the user to the group.

However, this is not the only error that prevents the desired result! Let us please give a more elaborate example:

Long Version (comprehensive)

Artifactory API Issue

When looking into the error above, we noticed the following behavior of the PACH access/api/v2/users/{name} endpoint: When patching this endpoint with the field "internal_password_disabled": false. This always raises the 400 error "Error: BAD_REQUEST - Cannot create a user without a password". According to the documentation, this should only be the case is this field is changed from "true" to "false", but apparently not. We opened a support ticket with Artifactory for this and tried to workaround this issue.

Step 1: Creater User

We want to create a user with "internal_password_disabled": true"(since the provider always sends field on update). However, wenn trying

resource "artifactory_user" "test_user" {
  name                       = "max_power"
  email                      = "max.power@test.invalid"
  admin                      = false
  profile_updatable          = true
  disable_ui_access          = false
  internal_password_disabled = true
  groups                     = []
}

Interestingly, this fails with

│ 
│ Error: BAD_REQUEST - Cannot set a password to a user for user with disabled internal password ('internal_password_disabled'=true)
╵

which is because the provider tries to set a dummy random password... so we return to first
setting

resource "artifactory_user" "test_user" {
  name                       = "max_power"
  email                      = "max.power@test.invalid"
  admin                      = false
  profile_updatable          = true
  disable_ui_access          = false
  internal_password_disabled = false
  groups                     = []
}

and then update the user with

resource "artifactory_user" "test_user" {
  name                       = "max_power"
  email                      = "max.power@test.invalid"
  admin                      = false
  profile_updatable          = true
  disable_ui_access          = false
  internal_password_disabled = true
  groups                     = []
}

Unfortunately, this does not work either since now we get an error

│ 
│ Error: BAD_REQUEST - Cant remove group that are not associated with the user
╵

This is now because the provider attempts to per default remove the "readers" group. However, this group has already been removed behind the scenes after creating the user. So we just add it:

resource "artifactory_user" "test_user" {
  name                       = "max_power"
  email                      = "max.power@test.invalid"
  admin                      = false
  profile_updatable          = true
  disable_ui_access          = false
  internal_password_disabled = true
  groups                     = ["readers"]
}

This works. We have successfully created a user with internal_password_disabled = true.
(Btw. even at this point has groups groups": [] when looking it up e.g. via API, but this is not important for us at this moment).

Step 2: Add it to a group

We now add the user to a group

resource "artifactory_user" "test_user" {
  name                       = "max_power"
  email                      = "max.power@test.invalid"
  admin                      = false
  profile_updatable          = true
  disable_ui_access          = false
  internal_password_disabled = true
  groups                     = ["readers", artifactory_group.test_group.name]
}


resource "artifactory_group" "test_group" {
  name             = "temp-test"
  description      = "temp-test"
  admin_privileges = false
  lifecycle {
    ignore_changes = [users_names]
  }
}

The terraform result looks fine, too. Even more, the state is stable (further planning does not show any changes)

However requesting now GET <ARTIFACTORY_URL>/access/api/v2/users/max_power gives us:

{
  "username": "max_power",
  "email": "max.power@test.invalid",
  "admin": false,
  "effective_admin": false,
  "profile_updatable": true,
  "disable_ui_access": false,
  "internal_password_disabled": true,
  "last_logged_in": "1970-01-01T00:00:00.000Z",
  "realm": "internal",
  "groups": [],
  "status": "enabled"
}

Expected behavior

The final "get" should give

{
  "username": "max_power",
  "email": "max.power@test.invalid",
  "admin": false,
  "effective_admin": false,
  "profile_updatable": true,
  "disable_ui_access": false,
  "internal_password_disabled": true,
  "last_logged_in": "1970-01-01T00:00:00.000Z",
  "realm": "internal",
  "groups": ["readers", "temp-test"],
  "status": "enabled"
}

Version

We are using provider jfrog/artifactory 10.3.3 with opentofu 1.6.2

Additional context

From our understanding, the PATCH <ARTIFACTORY_URL>/access/api/v2/users/{name} does not support changing user groups. From very briefly looking into the go implementation, we conclude the update function is possibly missing a dedicated step to update the groups again (via a call to UserGroupEndpointPath in additon to the removeReadersGroup call).

@fabiankle The first issue with user can't be created with a password when internal_password_disabled set to true is a bug in the provider. It should take into account internal_password_disabled when attempting to create a random password if password attribute is not set.

@fabiankle As for the groups attribute behavior, the cause is from this issue. The challenge here is that all groups that have autoJoin set to true will appear in the user.groups field after creation. This cause state drift unless those groups are specified in the configuration.

One solution is to compare the groups API field against the groups TF attribute and add/remove any groups as necessary (not just special group like 'readers').

--

As for your long scenario, I was not able to replicate the first issue in there. After I unset 'auto join' for the 'readers' group, I was able to create a new user (via API) with empty groups field. The API response also contains an empty groups field, thus should not cause a TF state drift (thus requiring add readers to groups attribute list). I'll try to replicate this in TF today.

Hi @alexhung ,

first of all thanks for the very quick reply!

In the end, the important thing for us would be to be able to adapt a user's group after it has been created (as mentioned we did open a ticket with Jfrog directly concerning internal_password_disabled issue, we're just convinced this alone will not fix our issue, hence the long version)

If it is any help for you, I could also provide you with the full logs (plan & apply) of the steps, please just let me know!

Best,
FAbian