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

Fix identity provider update and service account role management #171

Merged

Conversation

AndrewChubatiuk
Copy link
Contributor

@AndrewChubatiuk AndrewChubatiuk commented Oct 28, 2019

Hi @mrparkers
Prepared a PR with fixes for

  • OIDC identity provider: It doesn't keep a valid client_secret value during resource update
  • service account role: sometimes it doesn't save a full state and tries to recreate resource once again

@@ -123,6 +123,8 @@ func getOidcIdentityProviderFromData(data *schema.ResourceData) (*keycloak.Ident

if data.HasChange("client_secret") {
rec.Config.ClientSecret = data.Get("client_secret").(string)
} else {
rec.Config.ClientSecret = "**********"
Copy link
Owner

Choose a reason for hiding this comment

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

Is this going to send the string ********** to Keycloak on update? I'm wondering if it would be better to remove the if statement on line 124 and always call rec.Config.ClientSecret = data.Get("client_secret").(string) so Keycloak is always getting the correct client secret on every call.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is how actually browser is working

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Anyway I've updated it

}

func setOpenidClientServiceAccountRoleData(data *schema.ResourceData, serviceAccountRole *keycloak.OpenidClientServiceAccountRole) {
data.SetId(serviceAccountRole.Id)
data.SetId(fmt.Sprintf("%s/%s", serviceAccountRole.ServiceAccountUserId, serviceAccountRole.Id))
Copy link
Owner

Choose a reason for hiding this comment

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

This might be a breaking change since the ID for this resource is being changed. Can you verify that these resources aren't being recreated because of this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just new resources will be created. In context of service account roles it'll try to apply existing changes once to add service account roles with ned IDs but POST action to service account roles endpoint always returns 204 even if role was already added

realmId := data.Get("realm_id").(string)
serviceAccountRoleId := data.Get("service_account_user_id").(string)

if realmId != "" && containerId != "" {
Copy link
Owner

Choose a reason for hiding this comment

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

realm_id and client_id are both required attributes, so I think this statement is always true.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They can be empty if you're using realm_id = keycloak_realm.realm.id and client_id = keycloak_openid_client.client.id that do not exist yet

return err
}

if serviceAccountRole == nil {
Copy link
Owner

Choose a reason for hiding this comment

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

Can this error ever happen? I don't think it's possible for getOpenidClientServiceAccountRoleFromData to return nil without also returning an error.

return err
}

if serviceAccountRole == nil {
Copy link
Owner

Choose a reason for hiding this comment

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

Same comment as above


return keycloakClient.DeleteOpenidClientServiceAccountRole(realmId, serviceAccountUserId, clientId, id)
if serviceAccountRole != nil {
Copy link
Owner

Choose a reason for hiding this comment

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

Same comment as above, I don't think this can ever be false

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Had another problem. And tested locally this change, forgot to remove

@AndrewChubatiuk
Copy link
Contributor Author

@mrparkers Could you please take a look once again?


role, err := keycloakClient.GetRoleByName(realmId, containerId, roleName)
if err != nil {
if handleNotFoundError(err, data) == nil {
Copy link
Owner

Choose a reason for hiding this comment

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

This is going to call data.SetId("") if the error is s 404, which removes this resource from state. Is this what you want?

Copy link
Contributor Author

@AndrewChubatiuk AndrewChubatiuk Nov 1, 2019

Choose a reason for hiding this comment

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

yes, cause if role doesn't exist yet it cannot be attached/removed to/from a client.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Owner

Choose a reason for hiding this comment

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

What I mean is that the keycloak_openid_client_service_account_role resource will be removed from state if the GetRoleByName call fails with a 404. That seems problematic since ultimately this function won't return an error and the creation will appear to be successful.

If the keycloak_openid_client_service_account_roleresource isn't valid without an existing role, shouldn't create just fail?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When terraform plans resources creation it uses empty values for attributes of resource which is not yet created. Don't know how it should work, but at least have noticed such a behaviour for this provider. It'll cause errors during every plan when resources are not created yet. Without this check tests are always failing
https://circleci.com/gh/mrparkers/terraform-provider-keycloak/1152?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link


role, err := keycloakClient.GetRoleByName(realmId, containerId, roleName)
if err != nil {
if handleNotFoundError(err, data) == nil {
Copy link
Owner

Choose a reason for hiding this comment

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

Okay, your logic makes sense, thanks for the explanation. I think, however, that all you really want to do is check if the error is a 404 and not necessarily remove the resource from state.

Suggested change
if handleNotFoundError(err, data) == nil {
if keycloak.ErrorIs404(err) {

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 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mrparkers just updated

Copy link
Owner

@mrparkers mrparkers left a comment

Choose a reason for hiding this comment

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

Looks good, thanks for the contribution!

@mrparkers mrparkers merged commit 6fe6d6b into mrparkers:master Nov 4, 2019
@AndrewChubatiuk AndrewChubatiuk deleted the fix-identity-provider-update branch November 4, 2019 16:04
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.

2 participants