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

[JENKINS-74970] Log user name and repository if Bitbucket Server forbids posting a build status #965

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

KalleOlaviNiemitalo
Copy link
Contributor

@KalleOlaviNiemitalo KalleOlaviNiemitalo commented Jan 12, 2025

If Bitbucket Server responds with HTTP status 401 (Unauthorized) or 403 (Forbidden) when this plugin posts a build status, and the HTTP response includes an "X-AUSERNAME" header field that shows Bitbucket Server authenticated the user, then add more information in the message of the BitbucketRequestException:

  • The Bitbucket user name from the "X-AUSERNAME" response header field.
  • The repository to which the request was sent.
  • The project or user that owns the repository.

The behaviour is unchanged on Bitbucket Cloud, and on Bitbucket Server for operations other than posting a build status.

Your checklist for this pull request

  • Make sure you are requesting to pull a topic/feature/bugfix branch (right side) and not your master branch!
  • Ensure that the pull request title represents the desired changelog entry
  • Please describe what you did
  • Link to relevant issues in GitHub or in Jenkins JIRA
  • Link to relevant pull requests, esp. upstream and downstream changes
  • Did you provide a test-case? That demonstrates feature works or fixes the issue.

@KalleOlaviNiemitalo
Copy link
Contributor Author

Not yet happy with:

  • Would be nicer to show the permission actually required (REPO_READ, REPO_WRITE, or REPO_ADMIN).
  • If the REST API operation requires some other kind of permission (SYS_ADMIN, ADMIN, PROJECT_VIEW, PROJECT_CREATE, PROJECT_READ, PROJECT_WRITE, PROJECT_ADMIN, or LICENSED_USER), then the plugin should not add repository information to the exception, because granting permissions at the repository level will not help.
  • Documentation.

For the permission levels, I'm thinking the boolean requireAuthentication parameter of doRequest could be replaced with an enum, and then that would be passed to buildResponseException as well. This might require changing BitbucketCloudApiClient, too.

@nfalco79
Copy link
Member

The username is already logged because recently I have add all headers to the error message. This helped in JENKINS-75106
I would not start to specialize client classes for each HTTP code a message because sometimes could not fall into the case we thought.
Maybe could be useful show the URL of the request that already contains all details of workspace, project and repo_slug.

For the permission levels, I'm thinking the boolean requireAuthentication parameter of doRequest could be replaced with an enum, and then that would be passed to buildResponseException as well. This might require changing BitbucketCloudApiClient, too.

I can not keep track of each permission required for each API, and move forward useless parameter to methods only for logs.
At most we can add in case of 401 and 403 a link to the specific GitHub user documention. In this way is generic for both server/cloud and authentication type.

@KalleOlaviNiemitalo
Copy link
Contributor Author

recently I have add all headers to the error message

You mean response headers, right? Not request headers, which typically include secrets.

@KalleOlaviNiemitalo
Copy link
Contributor Author

For the permission levels, I'm thinking the boolean requireAuthentication parameter of doRequest could be replaced with an enum

This gets tricky in the getMirroredRepository method, where the request may require authentication, but the credentials are already included in the String url parameter.

Maybe could be useful show the URL of the request that already contains all details of workspace, project and repo_slug.

According to #829 (comment), the query component of the request URL can contain an authentication token. That should not be written to a log that users can read.

At this point, I'm thinking of adding to doRequest etc. a callback parameter (functional interface) and calling that instead of buildResponseException if not null. Only postBuildStatus would provide such a callback.

@nfalco79
Copy link
Member

You mean response headers, right? Not request headers, which typically include secrets.

Yes, request contains sensible information and username could be marked as "Treat username as secret" in credentials.
Response contains the X-AUSERNAME for server instance, not for cloud (at least when 401).
Maybe is acceptable "...username defined in credentialsId " + authenticator.getId() + " .... ensure the user is configured ..... see documentation at https://github......

@nfalco79
Copy link
Member

nfalco79 commented Jan 12, 2025

Maybe could be useful show the URL of the request that already contains all details of workspace, project and repo_slug.

According to #829 (comment), the query component of the request URL can contain an authentication token. That should not be written to a log that users can read.

Enrich the URLUtils#removeAuthority to remove also the jwt queryParam so it can be used for log

@nfalco79
Copy link
Member

At this point, I'm thinking of adding to doRequest etc. a callback parameter (functional interface) and calling that instead of buildResponseException if not null. Only postBuildStatus would provide such a callback.

You can improve the user documentation for that use case, I want share client code as much code as possible and not provide callback for which the called have to handle response and depends on http client code. See also pr #963 in case

@KalleOlaviNiemitalo
Copy link
Contributor Author

remove also the jwt queryParam

Does Atlassian document the name of the query parameter?

@nfalco79
Copy link
Member

Does Atlassian document the name of the query parameter?

No they speak about authenticated links

@KalleOlaviNiemitalo KalleOlaviNiemitalo changed the title [JENKINS-74970] Log user name and repository on auth error [JENKINS-74970] Log user name and repository if Bitbucket Server forbids posting a build status Jan 12, 2025
* @param response The HTTP response from Bitbucket.
* @return Advice to the user on why the request failed, or {@code null}.
*/
@CheckForNull String getAdvice(HttpResponse response);
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 HttpResponse rather than CloseableHttpResponse because the method should not close the response.

@KalleOlaviNiemitalo KalleOlaviNiemitalo force-pushed the JENKINS-74970-explain-auth-error branch from 3ecfe65 to a5a8dcb Compare January 13, 2025 08:46
If this plugin posts a build status to Bitbucket Server or Data Center,
but Bitbucket responds with HTTP status 401 (Unauthorized) or
403 (Forbidden), then log extra information to help users grant
Jenkins the required permission on the repository:

* The permission that is needed: REPO_READ.
* The Bitbucket user name.  Currently, this comes from the "X-AUSERNAME"
  response header field.
* The repository to which the request was sent.
* The project or user that owns the repository.

Because BitbucketServerAPIClient does not have direct access to a
TaskListener, it adds this information to the message of the
BitbucketRequestException, and the caller then logs it from there.

The behaviour on Bitbucket Cloud is unchanged.
@KalleOlaviNiemitalo KalleOlaviNiemitalo force-pushed the JENKINS-74970-explain-auth-error branch from a5a8dcb to 26ef0dd Compare January 13, 2025 09:28
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