Skip to content

Commit

Permalink
[SECURITY-49] Backing off from @Extension-based discovery.
Browse files Browse the repository at this point in the history
This is because we discovered some plugins that use Secret early on in
the initialization.
(cherry picked from commit c3d8e05)
  • Loading branch information
kohsuke committed Jan 5, 2013
1 parent 9fb6c2c commit 56e4b6e
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 56e4b6e

Please sign in to comment.