Skip to content

Commit dec3fc3

Browse files
authored
[JENKINS-75225] When configure job the list of credentials returns HTTP 504 (#985)
Limit the amount of time required to decryipt a password in case of com.cloudbees.jenkins.plugins.amazonecr.AmazonECSRegistryCredential credentials that takes long because perform rest operation to return password from the amazon vault.
1 parent bfeba3b commit dec3fc3

File tree

5 files changed

+92
-5
lines changed

5 files changed

+92
-5
lines changed

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/credentials/BitbucketAccessTokenAuthenticatorSource.java

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2222
* THE SOFTWARE.
2323
*/
24-
2524
package com.cloudbees.jenkins.plugins.bitbucket.impl.credentials;
2625

2726
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketAuthenticator;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Nikolas Falco
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package com.cloudbees.jenkins.plugins.bitbucket.impl.credentials;
25+
26+
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
27+
import com.google.common.util.concurrent.SimpleTimeLimiter;
28+
import com.google.common.util.concurrent.TimeLimiter;
29+
import edu.umd.cs.findbugs.annotations.NonNull;
30+
import hudson.util.Secret;
31+
import java.time.Duration;
32+
import java.util.concurrent.Executors;
33+
34+
final class BitbucketAuthenticatorUtils {
35+
36+
private BitbucketAuthenticatorUtils() {
37+
}
38+
39+
public static String getPassword(@NonNull UsernamePasswordCredentials credentials) throws InterruptedException {
40+
TimeLimiter timeLimiter = SimpleTimeLimiter.create(Executors.newSingleThreadExecutor());
41+
42+
try {
43+
// JENKINS-75225
44+
return timeLimiter.callWithTimeout(() -> Secret.toString(credentials.getPassword()), Duration.ofMillis(100));
45+
} catch (InterruptedException e) {
46+
// takes long maybe credentials are not stored in Jenkins and requires some rest call than will fail
47+
throw e;
48+
} catch (Exception e) {
49+
throw new RuntimeException(e);
50+
}
51+
}
52+
}

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/credentials/BitbucketOAuthCredentialMatcher.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import com.cloudbees.plugins.credentials.Credentials;
2828
import com.cloudbees.plugins.credentials.CredentialsMatcher;
2929
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
30-
import hudson.util.Secret;
3130
import java.util.logging.Level;
3231
import java.util.logging.Logger;
3332

@@ -62,7 +61,7 @@ public boolean matches(Credentials item) {
6261
String username = usernamePasswordCredential.getUsername();
6362
String password;
6463
try {
65-
password = Secret.toString(usernamePasswordCredential.getPassword());
64+
password = BitbucketAuthenticatorUtils.getPassword(usernamePasswordCredential);
6665
} catch (Exception e) {
6766
// JENKINS-75184
6867
return false;

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/impl/credentials/BitbucketUsernamePasswordCredentialMatcher.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import com.cloudbees.plugins.credentials.Credentials;
2727
import com.cloudbees.plugins.credentials.CredentialsMatcher;
2828
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
29-
import hudson.util.Secret;
3029
import org.apache.commons.lang.StringUtils;
3130

3231
// Although the CredentialsMatcher documentation says that the best practice
@@ -53,7 +52,7 @@ public boolean matches(Credentials item) {
5352
String username = usernamePasswordCredential.getUsername();
5453
String password;
5554
try {
56-
password = Secret.toString(usernamePasswordCredential.getPassword());
55+
password = BitbucketAuthenticatorUtils.getPassword(usernamePasswordCredential);
5756
} catch (Exception e) {
5857
// JENKINS-75184
5958
return false;

src/test/java/com/cloudbees/jenkins/plugins/bitbucket/impl/credentials/BitbucketOAuthCredentialMatcherTest.java

+38
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ void matches_returns_false_when_exception_getting_password() {
5353
assertThat(sut.matches(new ExceptionalCredentials())).isFalse();
5454
}
5555

56+
@Test
57+
@Issue("JENKINS-75225")
58+
void matches_returns_false_when_getting_password_takes_longer() {
59+
assertThat(sut.matches(new TakeLongCredentials())).isFalse();
60+
}
61+
5662
@SuppressWarnings("serial")
5763
private static class ExceptionalCredentials implements UsernamePasswordCredentials {
5864

@@ -79,4 +85,36 @@ public CredentialsDescriptor getDescriptor() {
7985
return null;
8086
}
8187
}
88+
89+
@SuppressWarnings("serial")
90+
private static class TakeLongCredentials implements UsernamePasswordCredentials {
91+
92+
@NonNull
93+
@Override
94+
public Secret getPassword() {
95+
try {
96+
Thread.sleep(1000);
97+
} catch (InterruptedException e) {
98+
throw new RuntimeException(e);
99+
}
100+
return Secret.fromString("password");
101+
}
102+
103+
@NonNull
104+
@Override
105+
public String getUsername() {
106+
return "dummy-username";
107+
}
108+
109+
@Override
110+
public CredentialsScope getScope() {
111+
return null;
112+
}
113+
114+
@NonNull
115+
@Override
116+
public CredentialsDescriptor getDescriptor() {
117+
return null;
118+
}
119+
}
82120
}

0 commit comments

Comments
 (0)