Skip to content

Commit

Permalink
Merge branch 'master' into token-lifetime
Browse files Browse the repository at this point in the history
  • Loading branch information
jglick authored Nov 21, 2022
2 parents b6cbddc + 3eace9d commit b30776b
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 5 deletions.
20 changes: 16 additions & 4 deletions src/main/java/io/jenkins/plugins/oidc_provider/Issuer.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

package io.jenkins.plugins.oidc_provider;

import com.cloudbees.plugins.credentials.Credentials;
import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.cloudbees.plugins.credentials.CredentialsStore;
import com.cloudbees.plugins.credentials.domains.Domain;
Expand All @@ -35,9 +36,10 @@
import hudson.model.ModelObject;
import hudson.model.Run;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Map;
import java.util.logging.Logger;
import jenkins.model.Jenkins;
import org.kohsuke.stapler.StaplerRequest;
import org.springframework.security.access.AccessDeniedException;
Expand All @@ -47,6 +49,8 @@
*/
public abstract class Issuer {

private static final Logger LOGGER = Logger.getLogger(Issuer.class.getName());

/**
* The associated object in Jenkins.
*/
Expand All @@ -60,14 +64,22 @@ public abstract class Issuer {
* @return a possibly empty set of credentials
*/
public final @NonNull Collection<? extends IdTokenCredentials> credentials() {
Map<String, IdTokenCredentials> credentials = new LinkedHashMap<>();
for (CredentialsProvider p : CredentialsProvider.enabled(context())) {
CredentialsStore store = p.getStore(context());
if (store != null) {
LOGGER.fine(() -> "found " + store + " for " + context());
// TODO should we consider other domains?
return store.getCredentials(Domain.global()).stream().filter(IdTokenCredentials.class::isInstance).map(IdTokenCredentials.class::cast).collect(Collectors.toList());
for (Credentials c : store.getCredentials(Domain.global())) {
if (c instanceof IdTokenCredentials) {
IdTokenCredentials itc = (IdTokenCredentials) c;
credentials.putIfAbsent(itc.getId(), itc);
}
}
}
}
return Collections.emptySet();
LOGGER.fine(() -> "in " + context() + " found " + credentials.keySet());
return credentials.values();
}

/**
Expand Down
61 changes: 60 additions & 1 deletion src/test/java/io/jenkins/plugins/oidc_provider/KeysTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,35 @@

package io.jenkins.plugins.oidc_provider;

import com.cloudbees.plugins.credentials.Credentials;
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.domains.Domain;
import com.gargoylesoftware.htmlunit.Page;
import hudson.ExtensionList;
import hudson.model.ItemGroup;
import hudson.model.ModelObject;
import hudson.security.Permission;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import jenkins.model.Jenkins;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.LoggerRule;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
import org.jvnet.hudson.test.TestExtension;

public class KeysTest {

Expand Down Expand Up @@ -72,4 +85,50 @@ public class KeysTest {
assertEquals("sig", key.getString("use"));
}

@Issue("https://github.com/jenkinsci/oidc-provider-plugin/issues/21")
@Test public void extraCredentialsProvider() throws Exception {
assertThat(ExtensionList.lookup(CredentialsProvider.class).get(0), instanceOf(ExtraProvider.class));
SystemCredentialsProvider.getInstance().getDomainCredentialsMap().get(Domain.global()).add(new IdTokenStringCredentials(CredentialsScope.GLOBAL, "global", null));
JSONObject config = r.getJSON("oidc/.well-known/openid-configuration").getJSONObject();
System.err.println(config.toString(2));
assertEquals(r.getURL() + "oidc", config.getString("issuer"));
JenkinsRule.WebClient wc = r.createWebClient();
Page p = wc.getPage(new URL(config.getString("jwks_uri")));
assertEquals("application/json", p.getWebResponse().getContentType());
JSONObject jwks = JSONObject.fromObject(p.getWebResponse().getContentAsString());
System.err.println(jwks.toString(2));
JSONArray keys = jwks.getJSONArray("keys");
assertEquals(1, keys.size());
JSONObject key = keys.getJSONObject(0);
assertEquals("global", key.getString("kid"));
}
@SuppressWarnings({"deprecation", "rawtypes"})
@TestExtension("extraCredentialsProvider") public static final class ExtraProvider extends CredentialsProvider {
@Override public <C extends Credentials> List<C> getCredentials(Class<C> type, ItemGroup itemGroup, org.acegisecurity.Authentication authentication) {
return Collections.emptyList();
}
@Override public CredentialsStore getStore(ModelObject object) {
return new CredentialsStore(ExtraProvider.class) {
@Override public ModelObject getContext() {
return object;
}
@Override public boolean hasPermission(org.acegisecurity.Authentication a, Permission permission) {
return true;
}
@Override public List<Credentials> getCredentials(Domain domain) {
return Collections.emptyList();
}
@Override public boolean addCredentials(Domain domain, Credentials credentials) throws IOException {
throw new IOException("no");
}
@Override public boolean removeCredentials(Domain domain, Credentials credentials) throws IOException {
throw new IOException("no");
}
@Override public boolean updateCredentials(Domain domain, Credentials current, Credentials replacement) throws IOException {
throw new IOException("no");
}
};
}
}

}

0 comments on commit b30776b

Please sign in to comment.