From 60d07a0073906db7d45aa43fdb09cdda162bbea6 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Thu, 26 Mar 2020 13:07:59 -0400 Subject: [PATCH 1/4] Cache app installation token --- .../github_branch_source/GitHubAppCredentials.java | 14 +++++++++++++- .../plugins/github_branch_source/JwtHelper.java | 11 +++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java b/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java index f5d5a176f..e13ba089d 100644 --- a/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java +++ b/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java @@ -12,6 +12,7 @@ import hudson.util.Secret; import java.io.IOException; import java.util.List; +import java.util.concurrent.TimeUnit; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.github.GHApp; @@ -39,6 +40,9 @@ public class GitHubAppCredentials extends BaseStandardCredentials implements Sta private String apiUri; + private transient String cachedToken; + private transient long tokenCacheTime; + @DataBoundConstructor @SuppressWarnings("unused") // by stapler public GitHubAppCredentials( @@ -105,7 +109,15 @@ public Secret getPassword() { apiUri = "https://api.github.com"; } - String appInstallationToken = generateAppInstallationToken(appID, privateKey.getPlainText(), apiUri); + long now = System.currentTimeMillis(); + String appInstallationToken; + if (cachedToken != null && now - tokenCacheTime < JwtHelper.VALIDITY_MS - /* takes some time to send requests */ TimeUnit.SECONDS.toMillis(10)) { + appInstallationToken = cachedToken; + } else { + appInstallationToken = generateAppInstallationToken(appID, privateKey.getPlainText(), apiUri); + cachedToken = appInstallationToken; + tokenCacheTime = now; + } return Secret.fromString(appInstallationToken); } diff --git a/src/main/java/org/jenkinsci/plugins/github_branch_source/JwtHelper.java b/src/main/java/org/jenkinsci/plugins/github_branch_source/JwtHelper.java index ef22228ba..8e339776c 100644 --- a/src/main/java/org/jenkinsci/plugins/github_branch_source/JwtHelper.java +++ b/src/main/java/org/jenkinsci/plugins/github_branch_source/JwtHelper.java @@ -10,12 +10,17 @@ import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; import java.util.Date; -import java.util.Objects; import static java.util.Objects.requireNonNull; +import java.util.concurrent.TimeUnit; class JwtHelper { + /** + * @see maximum JWT validity + */ + static final long VALIDITY_MS = TimeUnit.MINUTES.toMillis(10); + /** * Create a JWT for authenticating to GitHub as an app installation * @param githubAppId the app ID @@ -42,9 +47,7 @@ static String createJWT(String githubAppId, final String privateKey) { .setIssuer(githubAppId) .signWith(signingKey, signatureAlgorithm); - long oneMinuteInMillis = 60L * 1000L; - long expMillis = nowMillis + (oneMinuteInMillis * 8); - Date exp = new Date(expMillis); + Date exp = new Date(nowMillis + VALIDITY_MS); builder.setExpiration(exp); return builder.compact(); From 9da1f5a95d6d95de889d535b4b86741a82234cc7 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Thu, 26 Mar 2020 15:34:35 -0400 Subject: [PATCH 2/4] Back to 8m --- .../org/jenkinsci/plugins/github_branch_source/JwtHelper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugins/github_branch_source/JwtHelper.java b/src/main/java/org/jenkinsci/plugins/github_branch_source/JwtHelper.java index 8e339776c..abc498e0c 100644 --- a/src/main/java/org/jenkinsci/plugins/github_branch_source/JwtHelper.java +++ b/src/main/java/org/jenkinsci/plugins/github_branch_source/JwtHelper.java @@ -17,9 +17,9 @@ class JwtHelper { /** - * @see maximum JWT validity + * Somewhat less than the maximum JWT validity. */ - static final long VALIDITY_MS = TimeUnit.MINUTES.toMillis(10); + static final long VALIDITY_MS = TimeUnit.MINUTES.toMillis(8); /** * Create a JWT for authenticating to GitHub as an app installation From 6d8b52a9c46290aa0816b19ddc85f5278342dbc8 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Thu, 26 Mar 2020 15:40:47 -0400 Subject: [PATCH 3/4] Refresh the token when it is halfway toward expiration (4m), to be on the safe side --- .../plugins/github_branch_source/GitHubAppCredentials.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java b/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java index e13ba089d..4d4356e22 100644 --- a/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java +++ b/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java @@ -111,7 +111,7 @@ public Secret getPassword() { long now = System.currentTimeMillis(); String appInstallationToken; - if (cachedToken != null && now - tokenCacheTime < JwtHelper.VALIDITY_MS - /* takes some time to send requests */ TimeUnit.SECONDS.toMillis(10)) { + if (cachedToken != null && now - tokenCacheTime < JwtHelper.VALIDITY_MS /* extra buffer */ / 2) { appInstallationToken = cachedToken; } else { appInstallationToken = generateAppInstallationToken(appID, privateKey.getPlainText(), apiUri); From 023cdcabe957351eb0693c075d4891bbc5e738e0 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Thu, 26 Mar 2020 16:36:48 -0400 Subject: [PATCH 4/4] SpotBugs --- .../plugins/github_branch_source/GitHubAppCredentials.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java b/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java index 4d4356e22..e3cf34d75 100644 --- a/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java +++ b/src/main/java/org/jenkinsci/plugins/github_branch_source/GitHubAppCredentials.java @@ -5,6 +5,7 @@ import com.cloudbees.plugins.credentials.impl.BaseStandardCredentials; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; import hudson.Util; import hudson.util.FormValidation; @@ -28,6 +29,7 @@ import static org.jenkinsci.plugins.github_branch_source.GitHubSCMNavigator.DescriptorImpl.getPossibleApiUriItems; import static org.jenkinsci.plugins.github_branch_source.JwtHelper.createJWT; +@SuppressFBWarnings(value = "SE_NO_SERIALVERSIONID", justification = "XStream") public class GitHubAppCredentials extends BaseStandardCredentials implements StandardUsernamePasswordCredentials { private static final String ERROR_AUTHENTICATING_GITHUB_APP = "Couldn't authenticate with GitHub app ID %s";