-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for short-lived tokens (#138)
* Add support for short-lived tokens * Allow configuring short-lived access token expiry * Add retries for retrieving short-lived tokens * Update the implementation of the client * Require Bamboo 7.2.10 * Improve assertion and change the type
- Loading branch information
Showing
19 changed files
with
495 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
src/main/java/com/gradle/develocity/bamboo/DevelocityAccessCredential.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package com.gradle.develocity.bamboo; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
|
||
import java.util.Arrays; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
|
||
public final class DevelocityAccessCredential { | ||
|
||
private final String hostname; | ||
private final String key; | ||
|
||
private DevelocityAccessCredential(String hostname, String key) { | ||
this.hostname = hostname; | ||
this.key = key; | ||
} | ||
|
||
public static DevelocityAccessCredential of(String hostname, String key) { | ||
return new DevelocityAccessCredential(hostname, key); | ||
} | ||
|
||
public static Optional<DevelocityAccessCredential> parse(String rawAccessKey, String host) { | ||
return Arrays.stream(rawAccessKey.split(";")) | ||
.map(k -> k.split("=")) | ||
.filter(hostKey -> hostKey[0].equals(host)) | ||
.map(hostKey -> new DevelocityAccessCredential(hostKey[0], hostKey[1])) | ||
.findFirst(); | ||
} | ||
|
||
public static boolean isValid(String value) { | ||
if (StringUtils.isBlank(value)) { | ||
return false; | ||
} | ||
|
||
String[] entries = value.split(";"); | ||
|
||
for (String entry : entries) { | ||
String[] parts = entry.split("=", 2); | ||
if (parts.length < 2) { | ||
return false; | ||
} | ||
|
||
String servers = parts[0]; | ||
String accessKey = parts[1]; | ||
|
||
if (StringUtils.isBlank(servers) || StringUtils.isBlank(accessKey)) { | ||
return false; | ||
} | ||
|
||
for (String server : servers.split(",")) { | ||
if (StringUtils.isBlank(server)) { | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
public String getRawAccessKey() { | ||
return hostname + "=" + key; | ||
} | ||
|
||
public String getHostname() { | ||
return hostname; | ||
} | ||
|
||
public String getKey() { | ||
return key; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
DevelocityAccessCredential that = (DevelocityAccessCredential) o; | ||
return Objects.equals(hostname, that.hostname) && Objects.equals(key, that.key); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(hostname, key); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
src/main/java/com/gradle/develocity/bamboo/ShortLivedTokenClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package com.gradle.develocity.bamboo; | ||
|
||
import okhttp3.OkHttpClient; | ||
import okhttp3.Request; | ||
import okhttp3.RequestBody; | ||
import okhttp3.Response; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.io.IOException; | ||
import java.time.Duration; | ||
import java.util.Optional; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
@Component | ||
public class ShortLivedTokenClient { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(ShortLivedTokenClient.class); | ||
|
||
private static final RequestBody EMPTY_BODY = RequestBody.create(new byte[]{}); | ||
|
||
private static final int MAX_RETRIES = 3; | ||
private static final Duration RETRY_INTERVAL = Duration.ofSeconds(1); | ||
|
||
private final OkHttpClient httpClient; | ||
|
||
public ShortLivedTokenClient() { | ||
this.httpClient = new OkHttpClient().newBuilder() | ||
.callTimeout(10, TimeUnit.SECONDS) | ||
.build(); | ||
} | ||
|
||
public Optional<DevelocityAccessCredential> get(String server, DevelocityAccessCredential accessKey, String expiryInHours) { | ||
String url = normalize(server) + "api/auth/token"; | ||
if (StringUtils.isNotBlank(expiryInHours)) { | ||
url += "?expiresInHours=" + expiryInHours; | ||
} | ||
|
||
Request request = new Request.Builder() | ||
.url(url) | ||
.addHeader("Authorization", "Bearer " + accessKey.getKey()) | ||
.addHeader("Content-Type", "application/json") | ||
.post(EMPTY_BODY) | ||
.build(); | ||
|
||
int tryCount = 0; | ||
Integer errorCode = null; | ||
while (tryCount < MAX_RETRIES) { | ||
try (Response response = httpClient.newCall(request).execute()) { | ||
if (response.code() == 200 && response.body() != null) { | ||
return Optional.of(DevelocityAccessCredential.of(accessKey.getHostname(), response.body().string())); | ||
} else if (response.code() == 401) { | ||
LOGGER.warn("Short lived token request failed {} with status code 401", url); | ||
return Optional.empty(); | ||
} else { | ||
tryCount++; | ||
errorCode = response.code(); | ||
Thread.sleep(RETRY_INTERVAL.toMillis()); | ||
} | ||
} catch (IOException e) { | ||
LOGGER.warn("Short lived token request failed {}", url, e); | ||
return Optional.empty(); | ||
} catch (InterruptedException e) { | ||
// Ignore sleep exception as | ||
} | ||
} | ||
|
||
LOGGER.warn("Develocity short lived token request failed {} with status code {}", url, errorCode); | ||
return Optional.empty(); | ||
} | ||
|
||
private static String normalize(String server) { | ||
return server.endsWith("/") ? server : server + "/"; | ||
} | ||
|
||
} |
39 changes: 0 additions & 39 deletions
39
src/main/java/com/gradle/develocity/bamboo/admin/AccessKeyValidator.java
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.