Skip to content

Commit

Permalink
[JENKINS-58902] Non-user-scoped credentials are not shown when build …
Browse files Browse the repository at this point in the history
…authentication is configured

Fix CredentialProvider to gather system credentials when users have USE_ITEM  USE_OWN permission.
  • Loading branch information
nfalco79 committed Mar 1, 2024
1 parent e7f2f06 commit 04cd263
Showing 1 changed file with 66 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,54 @@
*/
package com.cloudbees.plugins.credentials;

import com.cloudbees.plugins.credentials.builds.CredentialsParameterBinding;
import static com.cloudbees.plugins.credentials.CredentialsStoreAction.FINGERPRINT_XML;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.Collator;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.jenkins.ui.icon.IconSpec;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.cloudbees.plugins.credentials.builds.CredentialsParameterBinder;
import com.cloudbees.plugins.credentials.builds.CredentialsParameterBinding;
import com.cloudbees.plugins.credentials.common.IdCredentials;
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
import com.cloudbees.plugins.credentials.fingerprints.ItemCredentialsFingerprintFacet;
import com.cloudbees.plugins.credentials.fingerprints.NodeCredentialsFingerprintFacet;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
Expand Down Expand Up @@ -62,48 +104,9 @@
import hudson.security.PermissionScope;
import hudson.security.SecurityRealm;
import hudson.util.ListBoxModel;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.Collator;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import jenkins.model.FingerprintFacet;
import jenkins.model.Jenkins;
import jenkins.util.Timer;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.jenkins.ui.icon.IconSpec;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import static com.cloudbees.plugins.credentials.CredentialsStoreAction.FINGERPRINT_XML;

/**
* An extension point for providing {@link Credentials}.
Expand Down Expand Up @@ -205,16 +208,16 @@ public abstract class CredentialsProvider extends Descriptor<CredentialsProvider
* The system property name corresponding to {@link #FINGERPRINT_ENABLED}.
*/
private static final String FINGERPRINT_ENABLED_NAME = CredentialsProvider.class.getSimpleName() + ".fingerprintEnabled";

/**
* Control if the fingerprints must be used or not.
* Control if the fingerprints must be used or not.
* By default they are activated and thus allow the tracking of credentials usage.
* In case of performance troubles in some weird situation, you can disable the behavior by setting it to {@code false}.
*/
@SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Accessible via System Groovy Scripts")
@Restricted(NoExternalUse.class)
/* package-protected */ static /* not final */ boolean FINGERPRINT_ENABLED = Boolean.parseBoolean(System.getProperty(FINGERPRINT_ENABLED_NAME, "true"));

/**
* Default constructor.
*/
Expand Down Expand Up @@ -560,7 +563,15 @@ public static <C extends Credentials> List<C> lookupCredentialsInItem(@NonNull C
for (CredentialsProvider provider : all()) {
if (provider.isEnabled(item) && provider.isApplicable(type)) {
try {
for (C c: provider.getCredentialsInItem(type, item, authentication, domainRequirements)) {
List<C> credentials = provider.getCredentialsInItem(type, item, authentication, domainRequirements);
// also lookup credentials as SYSTEM if granted for this item
if (authentication != ACL.SYSTEM2
&& (item.getACL().hasPermission2(authentication, CredentialsProvider.USE_ITEM)
|| item.getACL().hasPermission2(authentication, CredentialsProvider.USE_OWN))) {
credentials.addAll(provider.getCredentialsInItem(type, item, ACL.SYSTEM2, domainRequirements));
}

for (C c: credentials) {
if (!(c instanceof IdCredentials) || ids.add(((IdCredentials) c).getId())) {
// if IdCredentials, only add if we haven't added already
// if not IdCredentials, always add
Expand Down Expand Up @@ -633,9 +644,14 @@ public static <C extends IdCredentials> ListBoxModel listCredentialsInItem(@NonN
for (CredentialsProvider provider : all()) {
if (provider.isEnabled(item) && provider.isApplicable(type)) {
try {
for (ListBoxModel.Option option : provider.getCredentialIdsInItem(
type, item, authentication, domainRequirements, matcher == null ? CredentialsMatchers.always() : matcher)
) {
ListBoxModel credentialIds = provider.getCredentialIdsInItem(type, item, authentication, domainRequirements, matcher);
// also lookup credentials with scope SYSTEM when user has grants for this item
if (authentication != ACL.SYSTEM2
&& (item.getACL().hasPermission2(authentication, CredentialsProvider.USE_ITEM)
|| item.getACL().hasPermission2(authentication, CredentialsProvider.USE_OWN))) {
credentialIds.addAll(provider.getCredentialIdsInItem(type, item, ACL.SYSTEM2, domainRequirements, matcher));
}
for (ListBoxModel.Option option : credentialIds) {
if (ids.add(option.value)) {
result.add(option);
}
Expand Down Expand Up @@ -713,6 +729,7 @@ public static Iterable<CredentialsStore> lookupStores(final ModelObject context)
private Iterator<CredentialsProvider> iterator = providers.iterator();
private CredentialsStore next;

@Override
public boolean hasNext() {
if (next != null) {
return true;
Expand Down Expand Up @@ -773,6 +790,7 @@ public boolean hasNext() {
return false;
}

@Override
public CredentialsStore next() {
if (!hasNext()) {
throw new NoSuchElementException();
Expand Down Expand Up @@ -869,6 +887,7 @@ public static <C extends IdCredentials> C findCredentialById(@NonNull String id,
/**
* @deprecated Use {@link #findCredentialById(String, Class, Run, List)} instead.
*/
@Deprecated
public static <C extends IdCredentials> C findCredentialById(@NonNull String id, @NonNull Class<C> type,
@NonNull Run<?, ?> run,
DomainRequirement... domainRequirements) {
Expand Down

0 comments on commit 04cd263

Please sign in to comment.