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

Add User Management Resources #983

Merged
merged 8 commits into from
Oct 11, 2023
Merged

Add User Management Resources #983

merged 8 commits into from
Oct 11, 2023

Conversation

wsquan171
Copy link
Contributor

@wsquan171 wsquan171 commented Sep 21, 2023

This PR adds the following 3 resources related to user management:

  • Local users (/api/v1/node/users)
  • Roles (policy/api/v1/aaa/roles)
  • Role bindings (policy/api/v1/aaa/role-bindings)

Users

  • As password is not returned on GET, and it's possible for terraform created users to change the password out of terraform, password updates from config is not checked. Password resets could be done by deactivating then reactivate the same account.
  • SSH keys (api/v1/node/users/{userid}/ssh-keys) and auth policy (/api/v1/node/aaa/auth-policy) not included

Roles

  • Role validation API doesn't return error on invalid set of feature permissions. Instead, a list of "recommended" permissions will be returned. An error is raised reporting such missing permissions if the list is not empty.
  • Multi-tenancy API endpoints supports GET only, thus not included.

Role Bindings

  • For local users, role bindings is owned by NSX and created upon user creation. Role Binding Create and Delete is not allowed. Such role bindings must be imported into terraform for modifications.
  • To remove an entire path of a set of roles from a binding, the path needs to be marked for delete in the PUT call, with non-empty role in the list. A random role is picked from old state for the call to make NSX API validation pass.
  • Full CRUD for remote user bindings are tested with LDAP.
  • Acc test requires env NSXT_TEST_LDAP_USER to be set to a valid LDAP user, and NSX is enabled with LDAP identity source.

Partially resolve #943

@wsquan171 wsquan171 force-pushed the user-mgmt branch 2 times, most recently from 07f5f85 to 19f5dca Compare September 21, 2023 22:13

user, err := client.Createuser(userProp)
if err != nil {
return fmt.Errorf("failed to create Nsxt Node user: %s", err.Error())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use handleCreateError here for consistency, same below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
user, err := client.Get(id)
if err != nil {
if isNotFoundError(err) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behavior is covered with handleReadError

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@annakhm
Copy link
Collaborator

annakhm commented Sep 25, 2023

We have policy API for roles, but not for users?

@wsquan171 wsquan171 force-pushed the user-mgmt branch 3 times, most recently from f34d2f9 to a7507d2 Compare September 28, 2023 09:46
@vmwclabot
Copy link
Member

@wsquan171, you must sign every commit in this pull request acknowledging our Developer Certificate of Origin before your changes are merged. This can be done by adding Signed-off-by: John Doe <[email protected]> to the last line of each Git commit message. The e-mail address used to sign must match the e-mail address of the Git author. Click here to view the Developer Certificate of Origin agreement.

@vmwclabot vmwclabot added the dco-required DCO Required label Sep 28, 2023
@vmwclabot vmwclabot removed the dco-required DCO Required label Sep 28, 2023
@wsquan171 wsquan171 force-pushed the user-mgmt branch 2 times, most recently from 5dd38fe to a8e5802 Compare September 29, 2023 04:17
@wsquan171
Copy link
Contributor Author

We have policy API for roles, but not for users?

Unfortunately, yes. Local (node) users are only supported with management API.

@wsquan171
Copy link
Contributor Author

/test-all

1 similar comment
@wsquan171
Copy link
Contributor Author

/test-all

@wsquan171
Copy link
Contributor Author

/test-all


r := regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9@-_.\\-]*$")
if ok := r.MatchString(v); !ok {
es = append(es, fmt.Errorf("must be a valid username matching: ^[a-zA-Z][a-zA-Z0-9@-_.\\-]*$"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should expect users to understand regex..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed regex from the error message.

return handleReadError(d, "User", id, err)
}

// Password not return on GET
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would there be a non-empty diff after apply since password is not set in state?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per terraform dev guide:

If the Update callback returns with or without an error, the full state is saved. If the ID becomes blank, the resource is destroyed (even within an update, though this shouldn't happen except in error scenarios).

Verified that by changing only the password, terraform plan returns empty action plan after the initial apply, and reports:

No changes. Your infrastructure matches the configuration.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for verifying. Since password is not nested attribute, no problem indeed.

@wsquan171
Copy link
Contributor Author

/test-all

1 similar comment
@wsquan171
Copy link
Contributor Author

/test-all

// A second deletion attempt should be deemed as NotFound, which is then treated as successful.
var err error
for i := 0; i < 2; i++ {
err = client.Delete(id)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does the first delete always return error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essentially, the first DELETE call actually went through, with HTTP status 200. It's just the returned HTTP header content-type: text/html; charset=UTF-8 would always trigger sdk to report it back as internal server error, and such error type casting made checking status code very difficult on our end.

The second call will make NSX return 404, which is ignored on delete calls.

This issue still exists on NSX 4.1.2 rtqa.

},

Schema: map[string]*schema.Schema{
"display_name": getDataSourceDisplayNameSchema(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason we don't allow controlling nsx_id here and in the other policy resource?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For roles, role (role identifier) is used as the uuid in NSX, thus no other nsx_id is needed / supported.
For bindings, NSX does not allow providing an ID on create. It's a POST call under .../role-bindings URL, and the id can only be determined by NSX.

}
}

func policyUserManagementRolePatch(id string, d *schema.ResourceData, m interface{}) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the actual API call is Update and not Patch, I would suggest to change function name to improve readability

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed.

Schema: map[string]*schema.Schema{
"display_name": getDataSourceDisplayNameSchema(),
"description": getDataSourceDescriptionSchema(),
"revision": getRevisionSchema(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing path is not exposed in this API as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Neither role or role bindings exports policy path.

Signed-off-by: Shawn Wang <[email protected]>
@wsquan171
Copy link
Contributor Author

/test-all

@annakhm
Copy link
Collaborator

annakhm commented Oct 11, 2023

Thanks Shawn!

@annakhm
Copy link
Collaborator

annakhm commented Oct 11, 2023

/test-all

@wsquan171 wsquan171 merged commit bd0d7ce into vmware:master Oct 11, 2023
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

Successfully merging this pull request may close these issues.

Management of aaa resources (roles, role bindings, ...)
3 participants