Skip to content

Commit 04cd263

Browse files
committed
[JENKINS-58902] Non-user-scoped credentials are not shown when build authentication is configured
Fix CredentialProvider to gather system credentials when users have USE_ITEM USE_OWN permission.
1 parent e7f2f06 commit 04cd263

File tree

1 file changed

+66
-47
lines changed

1 file changed

+66
-47
lines changed

src/main/java/com/cloudbees/plugins/credentials/CredentialsProvider.java

+66-47
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,54 @@
2323
*/
2424
package com.cloudbees.plugins.credentials;
2525

26-
import com.cloudbees.plugins.credentials.builds.CredentialsParameterBinding;
26+
import static com.cloudbees.plugins.credentials.CredentialsStoreAction.FINGERPRINT_XML;
27+
28+
import java.io.IOException;
29+
import java.io.OutputStream;
30+
import java.io.OutputStreamWriter;
31+
import java.nio.charset.StandardCharsets;
32+
import java.security.DigestOutputStream;
33+
import java.security.MessageDigest;
34+
import java.security.NoSuchAlgorithmException;
35+
import java.text.Collator;
36+
import java.util.AbstractMap;
37+
import java.util.ArrayList;
38+
import java.util.Arrays;
39+
import java.util.Collection;
40+
import java.util.Collections;
41+
import java.util.Comparator;
42+
import java.util.HashSet;
43+
import java.util.Iterator;
44+
import java.util.LinkedHashSet;
45+
import java.util.List;
46+
import java.util.Locale;
47+
import java.util.Map;
48+
import java.util.NoSuchElementException;
49+
import java.util.Objects;
50+
import java.util.Set;
51+
import java.util.logging.Level;
52+
import java.util.logging.Logger;
53+
import java.util.stream.Collectors;
54+
55+
import org.apache.commons.io.IOUtils;
56+
import org.apache.commons.lang.StringUtils;
57+
import org.jenkins.ui.icon.IconSpec;
58+
import org.kohsuke.accmod.Restricted;
59+
import org.kohsuke.accmod.restrictions.DoNotUse;
60+
import org.kohsuke.accmod.restrictions.NoExternalUse;
61+
import org.kohsuke.stapler.Stapler;
62+
import org.kohsuke.stapler.StaplerRequest;
63+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
64+
import org.springframework.security.core.Authentication;
65+
import org.springframework.security.core.userdetails.UsernameNotFoundException;
66+
2767
import com.cloudbees.plugins.credentials.builds.CredentialsParameterBinder;
68+
import com.cloudbees.plugins.credentials.builds.CredentialsParameterBinding;
2869
import com.cloudbees.plugins.credentials.common.IdCredentials;
2970
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
3071
import com.cloudbees.plugins.credentials.fingerprints.ItemCredentialsFingerprintFacet;
3172
import com.cloudbees.plugins.credentials.fingerprints.NodeCredentialsFingerprintFacet;
73+
3274
import edu.umd.cs.findbugs.annotations.CheckForNull;
3375
import edu.umd.cs.findbugs.annotations.NonNull;
3476
import edu.umd.cs.findbugs.annotations.Nullable;
@@ -62,48 +104,9 @@
62104
import hudson.security.PermissionScope;
63105
import hudson.security.SecurityRealm;
64106
import hudson.util.ListBoxModel;
65-
import java.io.IOException;
66-
import java.io.OutputStream;
67-
import java.io.OutputStreamWriter;
68-
import java.nio.charset.StandardCharsets;
69-
import java.security.DigestOutputStream;
70-
import java.security.MessageDigest;
71-
import java.security.NoSuchAlgorithmException;
72-
import java.text.Collator;
73-
import java.util.AbstractMap;
74-
import java.util.ArrayList;
75-
import java.util.Arrays;
76-
import java.util.Collection;
77-
import java.util.Collections;
78-
import java.util.Comparator;
79-
import java.util.HashSet;
80-
import java.util.Iterator;
81-
import java.util.LinkedHashSet;
82-
import java.util.List;
83-
import java.util.Locale;
84-
import java.util.Map;
85-
import java.util.NoSuchElementException;
86-
import java.util.Objects;
87-
import java.util.Set;
88-
import java.util.logging.Level;
89-
import java.util.logging.Logger;
90-
import java.util.stream.Collectors;
91107
import jenkins.model.FingerprintFacet;
92108
import jenkins.model.Jenkins;
93109
import jenkins.util.Timer;
94-
import org.apache.commons.io.IOUtils;
95-
import org.apache.commons.lang.StringUtils;
96-
import org.jenkins.ui.icon.IconSpec;
97-
import org.kohsuke.accmod.Restricted;
98-
import org.kohsuke.accmod.restrictions.DoNotUse;
99-
import org.kohsuke.accmod.restrictions.NoExternalUse;
100-
import org.kohsuke.stapler.Stapler;
101-
import org.kohsuke.stapler.StaplerRequest;
102-
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
103-
import org.springframework.security.core.Authentication;
104-
import org.springframework.security.core.userdetails.UsernameNotFoundException;
105-
106-
import static com.cloudbees.plugins.credentials.CredentialsStoreAction.FINGERPRINT_XML;
107110

108111
/**
109112
* An extension point for providing {@link Credentials}.
@@ -205,16 +208,16 @@ public abstract class CredentialsProvider extends Descriptor<CredentialsProvider
205208
* The system property name corresponding to {@link #FINGERPRINT_ENABLED}.
206209
*/
207210
private static final String FINGERPRINT_ENABLED_NAME = CredentialsProvider.class.getSimpleName() + ".fingerprintEnabled";
208-
211+
209212
/**
210-
* Control if the fingerprints must be used or not.
213+
* Control if the fingerprints must be used or not.
211214
* By default they are activated and thus allow the tracking of credentials usage.
212215
* In case of performance troubles in some weird situation, you can disable the behavior by setting it to {@code false}.
213216
*/
214217
@SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Accessible via System Groovy Scripts")
215218
@Restricted(NoExternalUse.class)
216219
/* package-protected */ static /* not final */ boolean FINGERPRINT_ENABLED = Boolean.parseBoolean(System.getProperty(FINGERPRINT_ENABLED_NAME, "true"));
217-
220+
218221
/**
219222
* Default constructor.
220223
*/
@@ -560,7 +563,15 @@ public static <C extends Credentials> List<C> lookupCredentialsInItem(@NonNull C
560563
for (CredentialsProvider provider : all()) {
561564
if (provider.isEnabled(item) && provider.isApplicable(type)) {
562565
try {
563-
for (C c: provider.getCredentialsInItem(type, item, authentication, domainRequirements)) {
566+
List<C> credentials = provider.getCredentialsInItem(type, item, authentication, domainRequirements);
567+
// also lookup credentials as SYSTEM if granted for this item
568+
if (authentication != ACL.SYSTEM2
569+
&& (item.getACL().hasPermission2(authentication, CredentialsProvider.USE_ITEM)
570+
|| item.getACL().hasPermission2(authentication, CredentialsProvider.USE_OWN))) {
571+
credentials.addAll(provider.getCredentialsInItem(type, item, ACL.SYSTEM2, domainRequirements));
572+
}
573+
574+
for (C c: credentials) {
564575
if (!(c instanceof IdCredentials) || ids.add(((IdCredentials) c).getId())) {
565576
// if IdCredentials, only add if we haven't added already
566577
// if not IdCredentials, always add
@@ -633,9 +644,14 @@ public static <C extends IdCredentials> ListBoxModel listCredentialsInItem(@NonN
633644
for (CredentialsProvider provider : all()) {
634645
if (provider.isEnabled(item) && provider.isApplicable(type)) {
635646
try {
636-
for (ListBoxModel.Option option : provider.getCredentialIdsInItem(
637-
type, item, authentication, domainRequirements, matcher == null ? CredentialsMatchers.always() : matcher)
638-
) {
647+
ListBoxModel credentialIds = provider.getCredentialIdsInItem(type, item, authentication, domainRequirements, matcher);
648+
// also lookup credentials with scope SYSTEM when user has grants for this item
649+
if (authentication != ACL.SYSTEM2
650+
&& (item.getACL().hasPermission2(authentication, CredentialsProvider.USE_ITEM)
651+
|| item.getACL().hasPermission2(authentication, CredentialsProvider.USE_OWN))) {
652+
credentialIds.addAll(provider.getCredentialIdsInItem(type, item, ACL.SYSTEM2, domainRequirements, matcher));
653+
}
654+
for (ListBoxModel.Option option : credentialIds) {
639655
if (ids.add(option.value)) {
640656
result.add(option);
641657
}
@@ -713,6 +729,7 @@ public static Iterable<CredentialsStore> lookupStores(final ModelObject context)
713729
private Iterator<CredentialsProvider> iterator = providers.iterator();
714730
private CredentialsStore next;
715731

732+
@Override
716733
public boolean hasNext() {
717734
if (next != null) {
718735
return true;
@@ -773,6 +790,7 @@ public boolean hasNext() {
773790
return false;
774791
}
775792

793+
@Override
776794
public CredentialsStore next() {
777795
if (!hasNext()) {
778796
throw new NoSuchElementException();
@@ -869,6 +887,7 @@ public static <C extends IdCredentials> C findCredentialById(@NonNull String id,
869887
/**
870888
* @deprecated Use {@link #findCredentialById(String, Class, Run, List)} instead.
871889
*/
890+
@Deprecated
872891
public static <C extends IdCredentials> C findCredentialById(@NonNull String id, @NonNull Class<C> type,
873892
@NonNull Run<?, ?> run,
874893
DomainRequirement... domainRequirements) {

0 commit comments

Comments
 (0)