-
Notifications
You must be signed in to change notification settings - Fork 49
Adds support to create users with credentials #334
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
resource "okta_user" "test" { | ||
first_name = "TestAcc" | ||
last_name = "Smith" | ||
login = "test-acc-replace_with_uuid@example.com" | ||
email = "test-acc-replace_with_uuid@example.com" | ||
password = "Abcd1234" | ||
recovery_question = "What is the answer to life, the universe, and everything?" | ||
recovery_answer = "Forty Two" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
resource "okta_user" "test" { | ||
first_name = "TestAcc" | ||
last_name = "Smith" | ||
login = "test-acc-replace_with_uuid@example.com" | ||
email = "test-acc-replace_with_uuid@example.com" | ||
password = "SuperSecret007" | ||
recovery_question = "Which symbol has the ASCII code of Forty Two?" | ||
recovery_answer = "Asterisk" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,9 @@ var profileKeys = []string{ | |
"title", | ||
"user_type", | ||
"zip_code", | ||
"password", | ||
"recovery_question", | ||
"recovery_answer", | ||
} | ||
|
||
func resourceUser() *schema.Resource { | ||
|
@@ -265,6 +268,24 @@ func resourceUser() *schema.Resource { | |
Optional: true, | ||
Description: "User zipcode or postal code", | ||
}, | ||
"password": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Sensitive: true, | ||
Description: "User Password", | ||
}, | ||
"recovery_question": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Description: "User Password Recovery Question", | ||
}, | ||
"recovery_answer": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Sensitive: true, | ||
ValidateFunc: validation.StringLenBetween(4, 1000), | ||
Description: "User Password Recovery Answer", | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can either of these be updated? If so should we include them in the update logic? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, they can be updated. Let me include them in the update logic. Thanks for catching! |
||
}, | ||
} | ||
} | ||
|
@@ -291,7 +312,27 @@ func resourceUserCreate(d *schema.ResourceData, m interface{}) error { | |
qp = query.NewQueryParams(query.WithActivate(false)) | ||
} | ||
|
||
userBody := okta.User{Profile: profile} | ||
password := d.Get("password").(string) | ||
recoveryQuestion := d.Get("recovery_question").(string) | ||
recoveryAnswer := d.Get("recovery_answer").(string) | ||
|
||
uc := &okta.UserCredentials{ | ||
Password: &okta.PasswordCredential{ | ||
Value: password, | ||
}, | ||
} | ||
|
||
if recoveryQuestion != "" { | ||
uc.RecoveryQuestion = &okta.RecoveryQuestionCredential{ | ||
Question: recoveryQuestion, | ||
Answer: recoveryAnswer, | ||
} | ||
} | ||
|
||
userBody := okta.User{ | ||
Profile: profile, | ||
Credentials: uc, | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be cleaned up a bit, no need to instantiate the struct twice
|
||
user, _, err := client.User.CreateUser(userBody, qp) | ||
|
||
if err != nil { | ||
|
@@ -383,6 +424,9 @@ func resourceUserUpdate(d *schema.ResourceData, m interface{}) error { | |
roleChange := d.HasChange("admin_roles") | ||
groupChange := d.HasChange("group_memberships") | ||
userChange := hasProfileChange(d) | ||
passwordChange := d.HasChange("password") | ||
recoveryQuestionChange := d.HasChange("recovery_question") | ||
recoveryAnswerChange := d.HasChange("recovery_answer") | ||
|
||
// run the update status func first so a user that was previously deprovisioned | ||
// can be updated further if it's status changed in it's terraform configs | ||
|
@@ -423,6 +467,49 @@ func resourceUserUpdate(d *schema.ResourceData, m interface{}) error { | |
} | ||
d.SetPartial("group_memberships") | ||
} | ||
|
||
if passwordChange { | ||
oldPassword, newPassword := d.GetChange("password") | ||
|
||
op := &okta.PasswordCredential{ | ||
Value: oldPassword.(string), | ||
} | ||
np := &okta.PasswordCredential{ | ||
Value: newPassword.(string), | ||
} | ||
npr := &okta.ChangePasswordRequest{ | ||
OldPassword: op, | ||
NewPassword: np, | ||
} | ||
|
||
_, _, err := client.User.ChangePassword(d.Id(), *npr, nil) | ||
if err != nil { | ||
return fmt.Errorf("[ERROR] Error Updating User password in Okta: %v", err) | ||
} | ||
} | ||
|
||
if recoveryQuestionChange || recoveryAnswerChange { | ||
p := &okta.PasswordCredential{ | ||
Value: d.Get("password").(string), | ||
} | ||
|
||
rq := &okta.RecoveryQuestionCredential{ | ||
Question: d.Get("recovery_question").(string), | ||
Answer: d.Get("recovery_answer").(string), | ||
} | ||
|
||
nuc := &okta.UserCredentials{ | ||
Password: p, | ||
RecoveryQuestion: rq, | ||
} | ||
|
||
_, _, err := client.User.ChangeRecoveryQuestion(d.Id(), *nuc) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @quantumew - The recovery credentials update doesn't seem to work in my test environment. Okta APIs don't throw an error but the credentials are not updated in the user account. (Password is updated, but recovery question/answer is not). Trying to debug the issue. Don't merge this yet. |
||
|
||
if err != nil { | ||
return fmt.Errorf("[ERROR] Error Updating User password recovery credentials in Okta: %v", err) | ||
} | ||
} | ||
|
||
d.Partial(false) | ||
|
||
return resourceUserRead(d, m) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want this to be
Sensitive: true
. Can we also make it clear in the docs and description that this WILL be stored in plain text in state?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also looks like these properties are set on create only. Can we make that clear? "User's initial password. This value cannot be updated."
Technically these should be
ForceNew: true
if they can only be set on create. We should warn of that in the description.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically, okta has an API that allows you to update a user's password. The go lang SDK also has an API to do this - https://github.com/okta/okta-sdk-golang/blob/master/tests/integration/user_test.go#L237
Would we still need the
ForceNew: true
flag?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh coolio, no in that case we would just need to update our update function and support that. Hopefully I am reading this diff right, I am only seeing this logic in
resourceUserCreate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're reading it right. 😄
I will update the
resourceUserUpdate
function as well.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe I've addressed all your concerns. Take a look.