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

Handle grpc authentication errors #5297

Merged
merged 20 commits into from Sep 7, 2022

Conversation

antgamdia
Copy link
Contributor

Description of the change

As reported at #5295, the axios interceptor handling the logout does not work anymore (bc all the requests are handled by the grpc client).
This PR is to intercept the auth-related errors to force a programmatic logout.

Benefits

If an auth error happens, we will log the user out.

Possible drawbacks

Maybe we don't want to kick the user out in some points, but we can fine-tune it later.

Applicable issues

Additional information

Problem: I've found some grpc calls NOT returning the proper status code... this forced me to add some ugly workarounds looking for certain keywords to appear to detect a true auth error.

Demo:

errorsAuth

WIP as there are still several test cases to fix

Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
@netlify
Copy link

netlify bot commented Sep 2, 2022

Deploy Preview for kubeapps-dev canceled.

Built without sensitive environment variables

Name Link
🔨 Latest commit 5469f1d
🔍 Latest deploy log https://app.netlify.com/sites/kubeapps-dev/deploys/6317cc0e08c68d00080d144c

Comment on lines 133 to 141
if (e.constructor === UnauthorizedError) {
dispatch(actions.auth.logoutByAuthenticationError());
} else {
dispatch(
errorInstalledPackage(
new FetchWarning(
"this package has missing information, some actions might not be available.",
),
),
Copy link
Collaborator

Choose a reason for hiding this comment

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

There is actions.auth.logoutByAuthenticationError() repeated in many places.
I was wondering if we could refactor that to be generic with something like e.g. (pseudo-code):

export function handledErrorAction(err: ActionType<any>, e: any){
  if (e.constructor === UnauthorizedError) {
    return actions.auth.logoutByAuthenticationError();
  } else {
     return err;
  }
}

So that invocations can be almost a one-liner like e.g.:

dispatch(
      handledErrorAction(errorInstalledPackage(new FetchError("Unable to list apps", [e])), e)
)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, thanks! Will do!
Also, I'd like to explore the grpc interceptors at some point. Don't know if they can fit our main goal here, though. https://grpc.io/blog/grpc-web-interceptor/

return new NotFoundError(msg);
case grpc.Code.AlreadyExists:
return new ConflictError(msg);
case grpc.Code.InvalidArgument:
Copy link
Collaborator

Choose a reason for hiding this comment

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

InvalidArgument does not look like an internal server error? Maybe an error like e.g. UnprocessableEntity fits better?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is not, of course. This is tricky, as we aren't really actually using those error objects... so I just defaulted them to "server error" with no specific criteria.
Let's create error objects grouping some of them, as we may want to have them in the future. See what you think

Copy link
Collaborator

Choose a reason for hiding this comment

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

Agree with creating error objects that extend CustomError so that we can have some groups.

case grpc.Code.FailedPrecondition:
case grpc.Code.Internal:
//TODO(agamez): this code shouldn't be returned by the API, but it is
if (["credentials", "unauthorized"].some(p => msg?.toLowerCase()?.includes(p))) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

A bit weak, but I guess it is the only thing we can do until all error codes from backend are harmonized.

Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>

Conflicts:
	dashboard/src/shared/PackagesService.ts
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Signed-off-by: Antonio Gamez Diaz <agamez@vmware.com>
Copy link
Collaborator

@castelblanque castelblanque left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

@antgamdia antgamdia merged commit a9b90a8 into vmware-tanzu:main Sep 7, 2022
@antgamdia antgamdia deleted the 5295-handle-grpc-auth-error branch September 7, 2022 07:41
@antgamdia
Copy link
Contributor Author

antgamdia commented Sep 7, 2022

To investigate: using goharbor.com chart repo+ credentials + kicks me out, verify which grpc code we are returning when adding repos.
Edit: it happens when the Helm validation returns the response code from the repo, in this case, 401. But we should shallow this 401 and return a proper code instead. 400-alike maybe?

@castelblanque
Copy link
Collaborator

Tested the case, and it is returning a GRPC status 9 (Failed precondition).

grpc-message: Unable to add package repository "asdasda" using the plugin "helm.packages": rpc error: code = FailedPrecondition desc = Failed repository validation: &{401 {"errors":[{"code":"UNAUTHORIZED","message":"UnAuthorized"}]}%0A}
grpc-status: 9

That wraps the HTTP 401 returned by Harbor, indeed.

Maybe we need to process the 401 error in the backend and map it correctly. If it is a 401 that Harbor sends, I would return a grpc status 7 (Permission denied) or 3 (Invalid argument).
However, the PERMISSION_DENIED status could be confused with the user not having permissions to perform the operation itself in Kubeapps APIs, which is not the case. We might want to return instead the grpc status 3 (Invalid argument) and specify a more readable message text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Handle authentication errors in grpc calls
3 participants