Skip to content

Commit c14337a

Browse files
authored
[JENKINS-75477] Frequent 401 errors from Bitbucket Data Center when there are high concurrent builds (#1073)
Use CredentialsMatcher boxed in a timeout execution only when gathering the list of credentials for a web UI page, to exclude credentials that make remote calls to retrieve the password. In all other cases, when the plugin needs to look up stored credentials, it does not set the timebox on the secret.getPassword call, which causes an unpredictable
1 parent 6295ace commit c14337a

20 files changed

+315
-271
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
<connection>scm:git:https://github.com/${gitHubRepo}.git</connection>
6363
<developerConnection>scm:git:git@github.com:${gitHubRepo}.git</developerConnection>
6464
<url>https://github.com/${gitHubRepo}</url>
65-
<tag>936.4.1</tag>
65+
<tag>${scmTag}</tag>
6666
</scm>
6767

6868
<dependencyManagement>

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketGitSCMBuilder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketServerEndpoint;
3535
import com.cloudbees.jenkins.plugins.bitbucket.impl.extension.FallbackToOtherRepositoryGitSCMExtension;
3636
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils;
37-
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentials;
37+
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentialsUtils;
3838
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.SCMUtils;
3939
import com.cloudbees.jenkins.plugins.sshcredentials.SSHUserPrivateKey;
4040
import com.cloudbees.plugins.credentials.Credentials;
@@ -173,9 +173,9 @@ public BitbucketSCMSource scmSource() {
173173
@NonNull
174174
public BitbucketGitSCMBuilder withCredentials(String credentialsId, BitbucketRepositoryProtocol protocol) {
175175
if (StringUtils.isNotBlank(credentialsId)) {
176-
StandardCredentials credentials = BitbucketCredentials.lookupCredentials(
177-
scmSource.getServerUrl(),
176+
StandardCredentials credentials = BitbucketCredentialsUtils.lookupCredentials(
178177
scmSource.getOwner(),
178+
scmSource.getServerUrl(),
179179
credentialsId,
180180
StandardCredentials.class
181181
);

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMNavigator.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketServerEndpoint;
3737
import com.cloudbees.jenkins.plugins.bitbucket.impl.avatars.BitbucketTeamAvatarMetadataAction;
3838
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils;
39-
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentials;
39+
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentialsUtils;
4040
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.MirrorListSupplier;
4141
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.URLUtils;
4242
import com.cloudbees.jenkins.plugins.bitbucket.server.BitbucketServerWebhookImplementation;
@@ -249,9 +249,9 @@ public void visitSources(SCMSourceObserver observer) throws IOException, Interru
249249
listener.getLogger().format("Must specify a repository owner%n");
250250
return;
251251
}
252-
StandardCredentials credentials = BitbucketCredentials.lookupCredentials(
253-
serverUrl,
252+
StandardCredentials credentials = BitbucketCredentialsUtils.lookupCredentials(
254253
observer.getContext(),
254+
serverUrl,
255255
credentialsId,
256256
StandardCredentials.class
257257
);
@@ -302,9 +302,9 @@ public List<Action> retrieveActions(@NonNull SCMNavigatorOwner owner,
302302
// TODO when we have support for trusted events, use the details from event if event was from trusted source
303303
listener.getLogger().printf("Looking up team details of %s...%n", getRepoOwner());
304304
List<Action> result = new ArrayList<>();
305-
StandardCredentials credentials = BitbucketCredentials.lookupCredentials(
306-
serverUrl,
305+
StandardCredentials credentials = BitbucketCredentialsUtils.lookupCredentials(
307306
owner,
307+
serverUrl,
308308
credentialsId,
309309
StandardCredentials.class
310310
);
@@ -393,6 +393,7 @@ public boolean isServerUrlSelectable() {
393393
return !BitbucketEndpointProvider.all().isEmpty();
394394
}
395395

396+
@RequirePOST
396397
public ListBoxModel doFillServerUrlItems(@AncestorInPath SCMSourceOwner context) {
397398
AccessControlled contextToCheck = context == null ? Jenkins.get() : context;
398399
if (!contextToCheck.hasPermission(Item.CONFIGURE)) {
@@ -403,9 +404,9 @@ public ListBoxModel doFillServerUrlItems(@AncestorInPath SCMSourceOwner context)
403404

404405
@RequirePOST
405406
public static FormValidation doCheckCredentialsId(@AncestorInPath SCMSourceOwner context,
406-
@QueryParameter(fixEmpty = true, value = "serverUrl") String serverURL,
407+
@QueryParameter(fixEmpty = true, value = "serverUrl", required = true) String serverURL,
407408
@QueryParameter String value) {
408-
return BitbucketCredentials.checkCredentialsId(context, value, serverURL);
409+
return BitbucketCredentialsUtils.checkCredentialsId(context, value, serverURL);
409410
}
410411

411412
@RequirePOST
@@ -421,16 +422,17 @@ public static FormValidation doCheckMirrorId(@QueryParameter String value,
421422
return FormValidation.ok();
422423
}
423424

425+
@RequirePOST
424426
public ListBoxModel doFillCredentialsIdItems(@AncestorInPath SCMSourceOwner context,
425-
@QueryParameter(fixEmpty = true, value = "serverUrl") String serverURL) {
426-
return BitbucketCredentials.fillCredentialsIdItems(context, serverURL);
427+
@QueryParameter(fixEmpty = true, value = "serverUrl", required = true) String serverURL) {
428+
return BitbucketCredentialsUtils.listCredentials(context, serverURL, null);
427429
}
428430

431+
@RequirePOST
429432
public ListBoxModel doFillMirrorIdItems(@AncestorInPath SCMSourceOwner context,
430-
@QueryParameter(fixEmpty = true, value = "serverUrl") String serverUrl,
433+
@QueryParameter(fixEmpty = true, value = "serverUrl", required = true) String serverUrl,
431434
@QueryParameter String credentialsId,
432-
@QueryParameter String repoOwner)
433-
throws FormFillFailure {
435+
@QueryParameter String repoOwner) throws FormFillFailure {
434436
return getFromBitbucket(context, serverUrl, credentialsId, repoOwner, null, MirrorListSupplier.INSTANCE);
435437
}
436438

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
import com.cloudbees.jenkins.plugins.bitbucket.impl.extension.GitClientAuthenticatorExtension;
5151
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils;
5252
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketApiUtils.BitbucketSupplier;
53-
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentials;
53+
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentialsUtils;
5454
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.DateUtils;
5555
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.MirrorListSupplier;
5656
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.URLUtils;
@@ -797,9 +797,9 @@ public DescriptorImpl getDescriptor() {
797797

798798
@CheckForNull
799799
/* package */ StandardCredentials credentials() {
800-
return BitbucketCredentials.lookupCredentials(
801-
getServerUrl(),
800+
return BitbucketCredentialsUtils.lookupCredentials(
802801
getOwner(),
802+
getServerUrl(),
803803
getCredentialsId(),
804804
StandardCredentials.class
805805
);
@@ -1054,7 +1054,7 @@ public String getDisplayName() {
10541054
public FormValidation doCheckCredentialsId(@CheckForNull @AncestorInPath SCMSourceOwner context,
10551055
@QueryParameter String value,
10561056
@QueryParameter(fixEmpty = true, value = "serverUrl") String serverURL) {
1057-
return BitbucketCredentials.checkCredentialsId(context, value, serverURL);
1057+
return BitbucketCredentialsUtils.checkCredentialsId(context, value, serverURL);
10581058
}
10591059

10601060
public static FormValidation doCheckServerUrl(@AncestorInPath SCMSourceOwner context, @QueryParameter String value) {
@@ -1095,7 +1095,7 @@ public ListBoxModel doFillServerUrlItems(@AncestorInPath SCMSourceOwner context)
10951095
}
10961096

10971097
public ListBoxModel doFillCredentialsIdItems(@AncestorInPath SCMSourceOwner context, @QueryParameter String serverUrl) {
1098-
return BitbucketCredentials.fillCredentialsIdItems(context, serverUrl);
1098+
return BitbucketCredentialsUtils.listCredentials(context, serverUrl, null);
10991099
}
11001100

11011101
@RequirePOST

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/BitbucketApiFactory.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ protected BitbucketApi create(@Nullable String serverUrl,
7979
* Creates a {@link BitbucketApi} for the specified URL with the supplied credentials, owner and (optional)
8080
* repository.
8181
*
82-
* @param serverUrl the server URL.
82+
* @param serverURL the server URL.
8383
* @param authenticator the (optional) authenticator.
8484
* @param owner the owner name.
8585
* @param projectKey the (optional) project key.
@@ -88,17 +88,17 @@ protected BitbucketApi create(@Nullable String serverUrl,
8888
* @throws IllegalArgumentException if the supplied URL is not supported.
8989
*/
9090
@NonNull
91-
public static BitbucketApi newInstance(@Nullable String serverUrl,
91+
public static BitbucketApi newInstance(@Nullable String serverURL,
9292
@Nullable BitbucketAuthenticator authenticator,
9393
@NonNull String owner,
9494
@CheckForNull String projectKey,
9595
@CheckForNull String repository) {
9696
for (BitbucketApiFactory factory : ExtensionList.lookup(BitbucketApiFactory.class)) {
97-
if (factory.isMatch(serverUrl)) {
98-
return factory.create(serverUrl, authenticator, owner, projectKey, repository);
97+
if (factory.isMatch(serverURL)) {
98+
return factory.create(serverURL, authenticator, owner, projectKey, repository);
9999
}
100100
}
101-
throw new IllegalArgumentException("Unsupported Bitbucket server URL: " + serverUrl);
101+
throw new IllegalArgumentException("Unsupported Bitbucket server URL: " + serverURL);
102102
}
103103

104104
@NonNull

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/endpoint/BitbucketEndpoint.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
package com.cloudbees.jenkins.plugins.bitbucket.api.endpoint;
2525

2626
import com.cloudbees.jenkins.plugins.bitbucket.BitbucketSCMSource;
27-
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentials;
27+
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentialsUtils;
2828
import com.cloudbees.plugins.credentials.common.StandardCredentials;
2929
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
3030
import edu.umd.cs.findbugs.annotations.CheckForNull;
@@ -128,7 +128,7 @@ default StandardCredentials credentials() {
128128
if (credentialsId == null) {
129129
return null;
130130
} else {
131-
return BitbucketCredentials.lookupCredentials(getServerURL(), Jenkins.get(), credentialsId, StandardCredentials.class);
131+
return BitbucketCredentialsUtils.lookupCredentials(Jenkins.get(), getServerURL(), credentialsId, StandardCredentials.class);
132132
}
133133
}
134134

@@ -143,7 +143,7 @@ default StringCredentials hookSignatureCredentials() {
143143
if (credentialsId == null) {
144144
return null;
145145
} else {
146-
return BitbucketCredentials.lookupCredentials(getServerURL(), Jenkins.get(), credentialsId, StringCredentials.class);
146+
return BitbucketCredentialsUtils.lookupCredentials(Jenkins.get(), getServerURL(), credentialsId, StringCredentials.class);
147147
}
148148
}
149149

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/endpoint/BitbucketEndpointDescriptor.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@
2323
*/
2424
package com.cloudbees.jenkins.plugins.bitbucket.api.endpoint;
2525

26-
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentials;
26+
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentialsUtils;
2727
import com.cloudbees.plugins.credentials.CredentialsMatchers;
28-
import com.cloudbees.plugins.credentials.common.StandardCredentials;
2928
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
3029
import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder;
3130
import hudson.Util;
@@ -59,7 +58,7 @@ public class BitbucketEndpointDescriptor extends Descriptor<BitbucketEndpoint> {
5958
public ListBoxModel doFillCredentialsIdItems(@QueryParameter(fixEmpty = true) String credentialsId,
6059
@QueryParameter(value = "serverUrl", fixEmpty = true) String serverURL) {
6160
Jenkins jenkins = checkPermission();
62-
return BitbucketCredentials.fillCredentialsIdItems(serverURL, jenkins, StandardCredentials.class, credentialsId);
61+
return BitbucketCredentialsUtils.listCredentials(jenkins, serverURL, credentialsId);
6362
}
6463

6564
private static Jenkins checkPermission() {

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/endpoints/AbstractBitbucketEndpoint.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import com.cloudbees.jenkins.plugins.bitbucket.api.endpoint.BitbucketEndpoint;
2828
import com.cloudbees.jenkins.plugins.bitbucket.api.endpoint.BitbucketEndpointDescriptor;
2929
import com.cloudbees.jenkins.plugins.bitbucket.api.endpoint.BitbucketEndpointProvider;
30-
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentials;
30+
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentialsUtils;
3131
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.URLUtils;
3232
import com.cloudbees.plugins.credentials.common.StandardCredentials;
3333
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
@@ -259,7 +259,7 @@ public final String getCredentialsId() {
259259
@Override
260260
@CheckForNull
261261
public StandardCredentials credentials() {
262-
return BitbucketCredentials.lookupCredentials(getServerUrl(), Jenkins.get(), credentialsId, StandardCredentials.class);
262+
return BitbucketCredentialsUtils.lookupCredentials(Jenkins.get(), getServerUrl(), credentialsId, StandardCredentials.class);
263263
}
264264

265265
/**
@@ -270,7 +270,7 @@ public StandardCredentials credentials() {
270270
@Override
271271
@CheckForNull
272272
public StringCredentials hookSignatureCredentials() {
273-
return BitbucketCredentials.lookupCredentials(getServerUrl(), Jenkins.get(), hookSignatureCredentialsId, StringCredentials.class);
273+
return BitbucketCredentialsUtils.lookupCredentials(Jenkins.get(), getServerUrl(), hookSignatureCredentialsId, StringCredentials.class);
274274
}
275275

276276
/**

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/hooks/ServerPushEvent.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketAuthenticator;
3535
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketCommit;
3636
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketPullRequest;
37-
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentials;
37+
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentialsUtils;
3838
import com.cloudbees.jenkins.plugins.bitbucket.server.client.BitbucketServerAPIClient;
3939
import com.cloudbees.jenkins.plugins.bitbucket.server.client.branch.BitbucketServerCommit;
4040
import com.cloudbees.jenkins.plugins.bitbucket.server.client.pullrequest.BitbucketServerPullRequest;
@@ -197,9 +197,9 @@ private void addBranchesAndTags(BitbucketSCMSource src, Map<SCMHead, SCMRevision
197197
protected BitbucketApi getClient(BitbucketSCMSource src) {
198198
String serverURL = src.getServerUrl();
199199

200-
StandardCredentials credentials = BitbucketCredentials.lookupCredentials(
201-
serverURL,
200+
StandardCredentials credentials = BitbucketCredentialsUtils.lookupCredentials(
202201
src.getOwner(),
202+
serverURL,
203203
src.getCredentialsId(),
204204
StandardCredentials.class
205205
);

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/avatars/BitbucketAvatarImageSource.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketApi;
2727
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketApiFactory;
2828
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketAuthenticator;
29-
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentials;
29+
import com.cloudbees.jenkins.plugins.bitbucket.impl.util.BitbucketCredentialsUtils;
3030
import com.cloudbees.plugins.credentials.common.StandardCredentials;
3131
import edu.umd.cs.findbugs.annotations.NonNull;
3232
import edu.umd.cs.findbugs.annotations.Nullable;
@@ -68,7 +68,7 @@ public AvatarImage fetch() {
6868
owner = Jenkins.get().getItemByFullName(scmOwner, SCMNavigatorOwner.class);
6969
}
7070
if (owner != null) {
71-
StandardCredentials credentials = BitbucketCredentials.lookupCredentials(serverURL, owner, credentialsId, StandardCredentials.class);
71+
StandardCredentials credentials = BitbucketCredentialsUtils.lookupCredentials(owner, serverURL, credentialsId, StandardCredentials.class);
7272
BitbucketAuthenticator authenticator = AuthenticationTokens.convert(BitbucketAuthenticator.authenticationContext(serverURL), credentials);
7373
// projectKey and repository are not used to fetch the project avatar
7474
// owner can not be null but is not used from the client to retrieve avatar image, we just need authentication

0 commit comments

Comments
 (0)