From a5046761a6e821cb69116fe70182008384b8a5b3 Mon Sep 17 00:00:00 2001 From: Thomas Salzinger Date: Thu, 28 Mar 2024 09:47:04 +0100 Subject: [PATCH] Track credential usage within BitbucketCredentials#lookupCredentials The previous implementation actually missed out on a couple of usages, for example within `BitbucketSCMNavigator`. --- .../bitbucket/BitbucketCredentials.java | 68 +++++++++++-------- .../plugins/bitbucket/BitbucketSCMSource.java | 19 ------ 2 files changed, 39 insertions(+), 48 deletions(-) diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketCredentials.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketCredentials.java index 12dc8b90f..32488696f 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketCredentials.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketCredentials.java @@ -24,6 +24,7 @@ package com.cloudbees.jenkins.plugins.bitbucket; import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketAuthenticator; +import com.cloudbees.plugins.credentials.Credentials; import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.common.StandardCertificateCredentials; @@ -32,6 +33,7 @@ import com.cloudbees.plugins.credentials.domains.URIRequirementBuilder; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.model.Item; import hudson.model.Queue; import hudson.model.queue.Tasks; import hudson.security.ACL; @@ -53,26 +55,34 @@ private BitbucketCredentials() { throw new IllegalAccessError("Utility class"); } + /** + * Performs a lookup of credentials for the given context. Additionally, usage of the credentials is tracked for the + * given {@link SCMSourceOwner} via {@link CredentialsProvider#track(Item, Credentials)} + */ @CheckForNull static T lookupCredentials(@CheckForNull String serverUrl, @CheckForNull SCMSourceOwner context, @CheckForNull String id, @NonNull Class type) { if (StringUtils.isNotBlank(id) && context != null) { - return CredentialsMatchers.firstOrNull( - CredentialsProvider.lookupCredentials( - type, - context, - context instanceof Queue.Task - ? Tasks.getDefaultAuthenticationOf((Queue.Task) context) - : ACL.SYSTEM, - URIRequirementBuilder.fromUri(serverUrl).build() - ), - CredentialsMatchers.allOf( - CredentialsMatchers.withId(id), - CredentialsMatchers.anyOf(CredentialsMatchers.instanceOf(type)) - ) + final T credentials = CredentialsMatchers.firstOrNull( + CredentialsProvider.lookupCredentials( + type, + context, + context instanceof Queue.Task + ? Tasks.getDefaultAuthenticationOf((Queue.Task) context) + : ACL.SYSTEM, + URIRequirementBuilder.fromUri(serverUrl).build() + ), + CredentialsMatchers.allOf( + CredentialsMatchers.withId(id), + CredentialsMatchers.anyOf(CredentialsMatchers.instanceOf(type)) + ) ); + + CredentialsProvider.track(context, credentials); + + return credentials; } return null; } @@ -87,13 +97,13 @@ static ListBoxModel fillCredentialsIdItems( return result; } result.includeMatchingAs( - context instanceof Queue.Task - ? Tasks.getDefaultAuthenticationOf((Queue.Task) context) - : ACL.SYSTEM, - context, - StandardCredentials.class, - URIRequirementBuilder.fromUri(serverUrl).build(), - AuthenticationTokens.matcher(BitbucketAuthenticator.authenticationContext(serverUrl)) + context instanceof Queue.Task + ? Tasks.getDefaultAuthenticationOf((Queue.Task) context) + : ACL.SYSTEM, + context, + StandardCredentials.class, + URIRequirementBuilder.fromUri(serverUrl).build(), + AuthenticationTokens.matcher(BitbucketAuthenticator.authenticationContext(serverUrl)) ); return result; } @@ -106,15 +116,15 @@ static FormValidation checkCredentialsId( AccessControlled contextToCheck = context == null ? Jenkins.get() : context; contextToCheck.checkPermission(CredentialsProvider.VIEW); if (CredentialsMatchers.firstOrNull( - CredentialsProvider.lookupCredentials( - StandardCertificateCredentials.class, - context, - context instanceof Queue.Task ? Tasks.getDefaultAuthenticationOf((Queue.Task) context) : ACL.SYSTEM, - URIRequirementBuilder.fromUri(serverUrl).build()), - CredentialsMatchers.allOf( - CredentialsMatchers.withId(value), - AuthenticationTokens.matcher(BitbucketAuthenticator.authenticationContext(serverUrl)) - ) + CredentialsProvider.lookupCredentials( + StandardCertificateCredentials.class, + context, + context instanceof Queue.Task ? Tasks.getDefaultAuthenticationOf((Queue.Task) context) : ACL.SYSTEM, + URIRequirementBuilder.fromUri(serverUrl).build()), + CredentialsMatchers.allOf( + CredentialsMatchers.withId(value), + AuthenticationTokens.matcher(BitbucketAuthenticator.authenticationContext(serverUrl)) + ) ) != null) { return FormValidation.warning("A certificate was selected. You will likely need to configure Checkout over SSH."); } diff --git a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java index 3fcdb92ce..88f3dd2ea 100644 --- a/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java +++ b/src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java @@ -48,7 +48,6 @@ import com.cloudbees.jenkins.plugins.bitbucket.server.client.BitbucketServerAPIClient; import com.cloudbees.jenkins.plugins.bitbucket.server.client.repository.BitbucketServerRepository; import com.cloudbees.plugins.credentials.CredentialsNameProvider; -import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.common.StandardCredentials; import com.damnhandy.uri.template.UriTemplate; import com.fasterxml.jackson.databind.util.StdDateFormat; @@ -63,7 +62,6 @@ import hudson.model.Action; import hudson.model.Actionable; import hudson.model.Item; -import hudson.model.Run; import hudson.model.TaskListener; import hudson.plugins.git.GitSCM; import hudson.scm.SCM; @@ -571,8 +569,6 @@ public void afterSave() { protected void retrieve(@CheckForNull SCMSourceCriteria criteria, @NonNull SCMHeadObserver observer, @CheckForNull SCMHeadEvent event, @NonNull TaskListener listener) throws IOException, InterruptedException { - - trackCredentialsUsage(); try (BitbucketSCMSourceRequest request = new BitbucketSCMSourceContext(criteria, observer) .withTraits(traits) .newRequest(this, listener)) { @@ -827,19 +823,9 @@ private void retrieveTags(final BitbucketSCMSourceRequest request) throws IOExce request.listener().getLogger().format("%n %d tags were processed%n", count); } - private void trackCredentialsUsage() { - final SCMSourceOwner owner = getOwner(); - if (owner != null) { - CredentialsProvider.track(owner, credentials()); - } - } - @Override protected SCMRevision retrieve(SCMHead head, TaskListener listener) throws IOException, InterruptedException { final BitbucketApi bitbucket = buildBitbucketClient(); - - trackCredentialsUsage(); - try { if (head instanceof PullRequestSCMHead) { PullRequestSCMHead h = (PullRequestSCMHead) head; @@ -1239,11 +1225,6 @@ public static void setEventDelaySeconds(int eventDelaySeconds) { BitbucketSCMSource.eventDelaySeconds = Math.min(300, Math.max(0, eventDelaySeconds)); } - public static BitbucketSCMSource findForRun(Run run) { - SCMSource s = SCMSource.SourceByItem.findSource(run.getParent()); - return s instanceof BitbucketSCMSource ? (BitbucketSCMSource) s : null; - } - private void initCloneLinks() { if (primaryCloneLinks == null) { BitbucketApi bitbucket = buildBitbucketClient();