diff --git a/pom.xml b/pom.xml
index 40639fd1..0dee8c64 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,7 +55,7 @@
org.jenkins-ci.plugins
credentials
- 2.1.0
+ 2.1.11
true
diff --git a/src/main/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider.java b/src/main/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider.java
index ee148d6d..c02fb508 100644
--- a/src/main/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider.java
+++ b/src/main/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProvider.java
@@ -28,11 +28,14 @@
import com.cloudbees.hudson.plugins.folder.AbstractFolderProperty;
import com.cloudbees.hudson.plugins.folder.AbstractFolderPropertyDescriptor;
import com.cloudbees.plugins.credentials.Credentials;
+import com.cloudbees.plugins.credentials.CredentialsMatcher;
import com.cloudbees.plugins.credentials.CredentialsMatchers;
+import com.cloudbees.plugins.credentials.CredentialsNameProvider;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.CredentialsStore;
import com.cloudbees.plugins.credentials.CredentialsStoreAction;
+import com.cloudbees.plugins.credentials.common.IdCredentials;
import com.cloudbees.plugins.credentials.domains.Domain;
import com.cloudbees.plugins.credentials.domains.DomainCredentials;
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
@@ -52,12 +55,14 @@
import hudson.security.AccessDeniedException2;
import hudson.security.Permission;
import hudson.util.CopyOnWriteMap;
+import hudson.util.ListBoxModel;
import java.io.IOException;
import java.io.ObjectStreamException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -119,21 +124,25 @@ public List getCredentials(@NonNull Class type, @N
public List getCredentials(@NonNull Class type, @Nullable ItemGroup itemGroup,
@Nullable Authentication authentication,
@NonNull List domainRequirements) {
- if (authentication == null) {
- authentication = ACL.SYSTEM;
- }
List result = new ArrayList();
+ Set ids = new HashSet();
if (ACL.SYSTEM.equals(authentication)) {
while (itemGroup != null) {
if (itemGroup instanceof AbstractFolder) {
final AbstractFolder> folder = AbstractFolder.class.cast(itemGroup);
FolderCredentialsProperty property = folder.getProperties().get(FolderCredentialsProperty.class);
if (property != null) {
- result.addAll(DomainCredentials.getCredentials(
+ for (C c : DomainCredentials.getCredentials(
property.getDomainCredentialsMap(),
type,
domainRequirements,
- CredentialsMatchers.always()));
+ CredentialsMatchers.always())) {
+ if (!(c instanceof IdCredentials) || ids.add(((IdCredentials) c).getId())) {
+ // if IdCredentials, only add if we havent added already
+ // if not IdCredentials, always add
+ result.add(c);
+ }
+ }
}
}
if (itemGroup instanceof Item) {
@@ -161,6 +170,61 @@ public List getCredentials(@NonNull Class type, @N
return super.getCredentials(type, item, authentication, domainRequirements);
}
+ /**
+ * {@inheritDoc}
+ */
+ @NonNull
+ @Override
+ public ListBoxModel getCredentialIds(@NonNull Class type,
+ @Nullable ItemGroup itemGroup,
+ @Nullable Authentication authentication,
+ @NonNull List domainRequirements,
+ @NonNull CredentialsMatcher matcher) {
+ ListBoxModel result = new ListBoxModel();
+ Set ids = new HashSet();
+ if (ACL.SYSTEM.equals(authentication)) {
+ while (itemGroup != null) {
+ if (itemGroup instanceof AbstractFolder) {
+ final AbstractFolder> folder = AbstractFolder.class.cast(itemGroup);
+ FolderCredentialsProperty property = folder.getProperties().get(FolderCredentialsProperty.class);
+ if (property != null) {
+ for (C c : DomainCredentials.getCredentials(
+ property.getDomainCredentialsMap(),
+ type,
+ domainRequirements,
+ matcher)) {
+ if (ids.add(c.getId())) {
+ result.add(CredentialsNameProvider.name(c), c.getId());
+ }
+ }
+ }
+ }
+ if (itemGroup instanceof Item) {
+ itemGroup = ((Item)itemGroup).getParent();
+ } else {
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @NonNull
+ @Override
+ public ListBoxModel getCredentialIds(@NonNull Class type, @NonNull Item item,
+ @Nullable Authentication authentication,
+ @NonNull List domainRequirements,
+ @NonNull CredentialsMatcher matcher) {
+ if (item instanceof AbstractFolder) {
+ // credentials defined in the folder should be available in the context of the folder
+ return getCredentialIds(type, (ItemGroup) item, authentication, domainRequirements, matcher);
+ }
+ return getCredentialIds(type, item.getParent(), authentication, domainRequirements, matcher);
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/test/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProviderTest.java b/src/test/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProviderTest.java
index 23b261a8..46c01a95 100644
--- a/src/test/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProviderTest.java
+++ b/src/test/java/com/cloudbees/hudson/plugins/folder/properties/FolderCredentialsProviderTest.java
@@ -25,25 +25,48 @@
import com.cloudbees.hudson.plugins.folder.Folder;
import com.cloudbees.plugins.credentials.CredentialsMatchers;
+import com.cloudbees.plugins.credentials.CredentialsNameProvider;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.CredentialsStore;
+import com.cloudbees.plugins.credentials.SystemCredentialsProvider;
+import com.cloudbees.plugins.credentials.common.IdCredentials;
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
import com.cloudbees.plugins.credentials.domains.Domain;
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
+import hudson.Launcher;
+import hudson.model.AbstractBuild;
+import hudson.model.AbstractProject;
+import hudson.model.BuildListener;
+import hudson.model.Computer;
+import hudson.model.FreeStyleBuild;
+import hudson.model.FreeStyleProject;
import hudson.model.Item;
import hudson.model.ItemGroup;
+import hudson.model.Result;
+import hudson.model.User;
import hudson.security.ACL;
+import hudson.tasks.BuildStepDescriptor;
+import hudson.tasks.Builder;
import hudson.util.ListBoxModel;
import java.io.IOException;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import jenkins.security.QueueItemAuthenticatorConfiguration;
+import org.acegisecurity.Authentication;
import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.hamcrest.StringDescription;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.MockAuthorizationStrategy;
+import org.jvnet.hudson.test.MockQueueItemAuthenticator;
+import org.jvnet.hudson.test.TestExtension;
+import org.kohsuke.stapler.DataBoundConstructor;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasProperty;
@@ -114,6 +137,218 @@ public void credentialsListableAtFolderScope() throws Exception {
assertThat(asItem.get(0).value, is("test-id"));
}
+ @Test
+ public void given_folderCredential_when_builtAsSystem_then_credentialFound() throws Exception {
+ Folder f = createFolder();
+ CredentialsStore folderStore = getFolderStore(f);
+ folderStore.addCredentials(Domain.global(),
+ new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "foo-manchu", "Dr. Fu Manchu", "foo",
+ "manchu"));
+ FreeStyleProject prj = f.createProject(FreeStyleProject.class, "job");
+ prj.getBuildersList().add(new HasCredentialBuilder("foo-manchu"));
+ r.buildAndAssertSuccess(prj);
+ }
+
+ @Test
+ public void given_folderCredential_when_builtAsUserWithUseItem_then_credentialFound() throws Exception {
+ Folder f = createFolder();
+ CredentialsStore folderStore = getFolderStore(f);
+ folderStore.addCredentials(Domain.global(),
+ new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "foo-manchu", "Dr. Fu Manchu", "foo",
+ "manchu"));
+ FreeStyleProject prj = f.createProject(FreeStyleProject.class, "job");
+ prj.getBuildersList().add(new HasCredentialBuilder("foo-manchu"));
+
+ JenkinsRule.DummySecurityRealm realm = r.createDummySecurityRealm();
+ r.jenkins.setSecurityRealm(realm);
+
+ MockAuthorizationStrategy strategy = new MockAuthorizationStrategy();
+ strategy.grant(CredentialsProvider.USE_ITEM).everywhere().to("bob");
+ strategy.grant(Item.BUILD).everywhere().to("bob");
+ strategy.grant(Computer.BUILD).everywhere().to("bob");
+
+ r.jenkins.setAuthorizationStrategy(strategy);
+ HashMap jobsToUsers = new HashMap();
+ jobsToUsers.put(prj.getFullName(), User.get("bob").impersonate());
+ MockQueueItemAuthenticator authenticator = new MockQueueItemAuthenticator(jobsToUsers);
+
+ QueueItemAuthenticatorConfiguration.get().getAuthenticators().clear();
+ QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(authenticator);
+ r.buildAndAssertSuccess(prj);
+ }
+
+ @Test
+ public void given_folderCredential_when_builtAsUserWithoutUseItem_then_credentialNotFound() throws Exception {
+ Folder f = createFolder();
+ CredentialsStore folderStore = getFolderStore(f);
+ folderStore.addCredentials(Domain.global(),
+ new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "foo-manchu", "Dr. Fu Manchu", "foo",
+ "manchu"));
+ FreeStyleProject prj = f.createProject(FreeStyleProject.class, "job");
+ prj.getBuildersList().add(new HasCredentialBuilder("foo-manchu"));
+
+ JenkinsRule.DummySecurityRealm realm = r.createDummySecurityRealm();
+ r.jenkins.setSecurityRealm(realm);
+
+ MockAuthorizationStrategy strategy = new MockAuthorizationStrategy();
+ strategy.grant(Item.BUILD).everywhere().to("bob");
+ strategy.grant(Computer.BUILD).everywhere().to("bob");
+
+ r.jenkins.setAuthorizationStrategy(strategy);
+ HashMap jobsToUsers = new HashMap();
+ jobsToUsers.put(prj.getFullName(), User.get("bob").impersonate());
+ MockQueueItemAuthenticator authenticator = new MockQueueItemAuthenticator(jobsToUsers);
+
+ QueueItemAuthenticatorConfiguration.get().getAuthenticators().clear();
+ QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(authenticator);
+ r.assertBuildStatus(Result.FAILURE, prj.scheduleBuild2(0).get());
+ }
+
+ @Test
+ public void given_folderAndSystemCredentials_when_builtAsUserWithUseItem_then_folderCredentialFound() throws Exception {
+ SystemCredentialsProvider.getInstance().getCredentials().add(
+ new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "foo-manchu", "You don't want me", "bar", "fly")
+ );
+ Folder f = createFolder();
+ CredentialsStore folderStore = getFolderStore(f);
+ folderStore.addCredentials(Domain.global(),
+ new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "foo-manchu", "Dr. Fu Manchu", "foo",
+ "manchu"));
+ FreeStyleProject prj = f.createProject(FreeStyleProject.class, "job");
+ prj.getBuildersList().add(new HasCredentialBuilder("foo-manchu", Matchers.hasProperty("username", is("foo"))));
+
+ JenkinsRule.DummySecurityRealm realm = r.createDummySecurityRealm();
+ r.jenkins.setSecurityRealm(realm);
+
+ MockAuthorizationStrategy strategy = new MockAuthorizationStrategy();
+ strategy.grant(CredentialsProvider.USE_ITEM).everywhere().to("bob");
+ strategy.grant(Item.BUILD).everywhere().to("bob");
+ strategy.grant(Computer.BUILD).everywhere().to("bob");
+
+ r.jenkins.setAuthorizationStrategy(strategy);
+ HashMap jobsToUsers = new HashMap();
+ jobsToUsers.put(prj.getFullName(), User.get("bob").impersonate());
+ MockQueueItemAuthenticator authenticator = new MockQueueItemAuthenticator(jobsToUsers);
+
+ QueueItemAuthenticatorConfiguration.get().getAuthenticators().clear();
+ QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(authenticator);
+ try {
+ r.buildAndAssertSuccess(prj);
+ } catch (Exception e) {
+ FreeStyleBuild build = prj.getLastBuild();
+ if (build != null) {
+ System.out.println(JenkinsRule.getLog(build));
+ }
+ throw e;
+ }
+ }
+
+ @Test
+ public void given_nestedFolderAndSystemCredentials_when_builtAsUserWithUseItem_then_folderCredentialFound() throws Exception {
+ SystemCredentialsProvider.getInstance().getCredentials().add(
+ new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "foo-manchu", "You don't want me", "bar", "fly")
+ );
+ Folder f = createFolder();
+ CredentialsStore folderStore = getFolderStore(f);
+ folderStore.addCredentials(Domain.global(),
+ new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "foo-manchu", "Prof. Xavier", "prof",
+ "xavier"));
+ Folder child = f.createProject(Folder.class, "child");
+ getFolderStore(child).addCredentials(Domain.global(),
+ new UsernamePasswordCredentialsImpl(CredentialsScope.GLOBAL, "foo-manchu", "Dr. Fu Manchu", "foo",
+ "manchu"));
+ FreeStyleProject prj = child.createProject(FreeStyleProject.class, "job");
+ prj.getBuildersList().add(new HasCredentialBuilder("foo-manchu", Matchers.hasProperty("username", is("foo"))));
+
+ JenkinsRule.DummySecurityRealm realm = r.createDummySecurityRealm();
+ r.jenkins.setSecurityRealm(realm);
+
+ MockAuthorizationStrategy strategy = new MockAuthorizationStrategy();
+ strategy.grant(CredentialsProvider.USE_ITEM).everywhere().to("bob");
+ strategy.grant(Item.BUILD).everywhere().to("bob");
+ strategy.grant(Computer.BUILD).everywhere().to("bob");
+
+ r.jenkins.setAuthorizationStrategy(strategy);
+ HashMap jobsToUsers = new HashMap();
+ jobsToUsers.put(prj.getFullName(), User.get("bob").impersonate());
+ MockQueueItemAuthenticator authenticator = new MockQueueItemAuthenticator(jobsToUsers);
+
+ QueueItemAuthenticatorConfiguration.get().getAuthenticators().clear();
+ QueueItemAuthenticatorConfiguration.get().getAuthenticators().add(authenticator);
+ try {
+ r.buildAndAssertSuccess(prj);
+ } catch (Exception e) {
+ FreeStyleBuild build = prj.getLastBuild();
+ if (build != null) {
+ System.out.println(JenkinsRule.getLog(build));
+ }
+ throw e;
+ }
+ }
+
+ public static class HasCredentialBuilder extends Builder {
+
+ private final String id;
+ private Matcher> matcher;
+
+ @DataBoundConstructor
+ public HasCredentialBuilder(String id) {
+ this.id = id;
+ }
+
+ public HasCredentialBuilder(String id, Matcher> matcher) {
+ this.id = id;
+ this.matcher = matcher;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public Matcher> getMatcher() {
+ return matcher;
+ }
+
+ @Override
+ public boolean perform(AbstractBuild, ?> build, Launcher launcher, BuildListener listener)
+ throws InterruptedException, IOException {
+ IdCredentials credentials = CredentialsProvider.findCredentialById(id, IdCredentials.class, build);
+ if (credentials == null) {
+ listener.getLogger().printf("Could not find any credentials with id %s%n", id);
+ build.setResult(Result.FAILURE);
+ return false;
+ } else {
+ listener.getLogger()
+ .printf("Found %s credentials with id %s%n", CredentialsNameProvider.name(credentials), id);
+ if (matcher != null) {
+ if (matcher.matches(credentials)) {
+ listener.getLogger().println("Credentials match criteria");
+ } else {
+ StringDescription description = new StringDescription();
+ matcher.describeMismatch(credentials, description);
+ listener.getLogger().println(description.toString());
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ @TestExtension
+ public static class DescriptorImpl extends BuildStepDescriptor {
+
+ @Override
+ public boolean isApplicable(Class extends AbstractProject> jobType) {
+ return true;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "Probe credentials exist";
+ }
+ }
+ }
+
private CredentialsStore getFolderStore(Folder f) {
Iterable stores = CredentialsProvider.lookupStores(f);
CredentialsStore folderStore = null;