Skip to content
Permalink
Browse files Browse the repository at this point in the history
[SECURITY-49] Backing off from @Extension-based discovery.
This is because we discovered some plugins that use Secret early on in
the initialization.
  • Loading branch information
kohsuke committed Jan 5, 2013
1 parent 4895eaa commit c3d8e05
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
42 changes: 39 additions & 3 deletions core/src/main/java/jenkins/security/ConfidentialStore.java
@@ -1,12 +1,20 @@
package jenkins.security;

import hudson.Extension;
import hudson.Lookup;
import hudson.init.InitMilestone;
import hudson.util.Secret;
import hudson.util.Service;
import jenkins.model.Jenkins;
import org.kohsuke.MetaInfServices;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* The actual storage for the data held by {@link ConfidentialKey}s, and the holder
Expand All @@ -18,8 +26,11 @@
*
* <p>
* OEM distributions of Jenkins can provide a custom {@link ConfidentialStore} implementation
* by writing a subclass, mark it with {@link Extension} annotation, package it as a Jenkins module,
* and bundling it with the war file.
* by writing a subclass, mark it with {@link MetaInfServices} annotation, package it as a Jenkins module,
* and bundling it with the war file. This doesn't use {@link Extension} because some plugins
* have been found to use {@link Secret} before we get to {@link InitMilestone#PLUGINS_PREPARED}, and
* therefore {@link Extension}s aren't loaded yet. (Similarly, it's conceivable that some future
* core code might need this early on during the boot sequence.)
*
* @author Kohsuke Kawaguchi
* @since 1.498
Expand Down Expand Up @@ -51,11 +62,36 @@ public abstract class ConfidentialStore {
*/
public static @Nonnull ConfidentialStore get() {
if (TEST!=null) return TEST.get();
return Jenkins.getInstance().getExtensionList(ConfidentialStore.class).get(0);

Lookup lookup = Jenkins.getInstance().lookup;
ConfidentialStore cs = lookup.get(ConfidentialStore.class);
if (cs==null) {
try {
List<ConfidentialStore> r = (List) Service.loadInstances(ConfidentialStore.class.getClassLoader(), ConfidentialStore.class);
if (!r.isEmpty())
cs = r.get(0);
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Failed to list up ConfidentialStore implementations",e);
// fall through
}

if (cs==null)
try {
cs = new DefaultConfidentialStore();
} catch (Exception e) {
// if it's still null, bail out
throw new Error(e);
}

cs = lookup.setIfNull(ConfidentialStore.class,cs);
}
return cs;
}

/**
* Testing only. Used for testing {@link ConfidentialKey} without {@link Jenkins}
*/
/*package*/ static ThreadLocal<ConfidentialStore> TEST = null;

private static final Logger LOGGER = Logger.getLogger(ConfidentialStore.class.getName());
}
@@ -1,6 +1,5 @@
package jenkins.security;

import hudson.Extension;
import hudson.FilePath;
import hudson.Util;
import hudson.util.IOException2;
Expand Down Expand Up @@ -28,7 +27,7 @@
*
* @author Kohsuke Kawaguchi
*/
@Extension(ordinal=-99999) // small ordinal value to allow other higher ones to take over
// @MetaInfServices --- not annotated because this is the fallback implementation
public class DefaultConfidentialStore extends ConfidentialStore {
private final SecureRandom sr = new SecureRandom();

Expand Down

0 comments on commit c3d8e05

Please sign in to comment.