Skip to content
Permalink
Browse files

Merge pull request #2185 from kzantow/JENKINS-33800-initial-password-…

…file-not-found

[JENKINS-33800] - fileNotFound exception / more accurately determine if this is an upgrade
  • Loading branch information...
daniel-beck committed Apr 5, 2016
2 parents e3ae368 + fcc547e commit 37c00cf2aff05dcefca78c60f498875ce20d911e
@@ -1194,7 +1194,6 @@ public void run() {
}
updateCenter.persistInstallStatus();
jenkins.setInstallState(InstallState.INITIAL_PLUGINS_INSTALLING.getNextState());
InstallUtil.saveLastExecVersion();
}
}.start();
}
@@ -53,7 +53,6 @@
import hudson.util.PersistedList;
import hudson.util.XStream2;
import jenkins.RestartRequiredException;
import jenkins.install.InstallState;
import jenkins.install.InstallUtil;
import jenkins.model.Jenkins;
import jenkins.util.io.OnMaster;
@@ -1913,18 +1912,14 @@ public int compareTo(PluginEntry o) {
@Initializer(after=PLUGINS_STARTED, fatal=false)
public static void init(Jenkins h) throws IOException {
h.getUpdateCenter().load();
if (Jenkins.getActiveInstance().getInstallState() == InstallState.NEW) {
LOGGER.log(INFO, "This is a new Jenkins instance. The Plugin Install Wizard will be launched.");
// Force update of the default site file (updates/default.json).
updateDefaultSite();
}
}

private static void updateDefaultSite() {
@Restricted(NoExternalUse.class)
public static void updateDefaultSite() {
try {
// Need to do the following because the plugin manager will attempt to access
// $JENKINS_HOME/updates/default.json. Needs to be up to date.
Jenkins.getActiveInstance().getUpdateCenter().getSite(UpdateCenter.ID_DEFAULT).updateDirectlyNow(true);
Jenkins.getInstance().getUpdateCenter().getSite(UpdateCenter.ID_DEFAULT).updateDirectlyNow(true);
} catch (Exception e) {
LOGGER.log(WARNING, "Upgrading Jenkins. Failed to update default UpdateSite. Plugin upgrades may fail.", e);
}
@@ -23,6 +23,8 @@
*/
package jenkins.install;

import javax.annotation.CheckForNull;

import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;

@@ -33,6 +35,10 @@
*/
@Restricted(NoExternalUse.class)
public enum InstallState {
/**
* Need InstallState != NEW for tests by default
*/
UNKNOWN(true, null),
/**
* The initial set up has been completed
*/
@@ -90,6 +96,7 @@ public boolean isSetupComplete() {
/**
* Gets the next state
*/
@CheckForNull
public InstallState getNextState() {
return nextState;
}
@@ -45,6 +45,10 @@
import hudson.Functions;
import hudson.model.UpdateCenter.DownloadJob.InstallationStatus;
import hudson.model.UpdateCenter.DownloadJob.Installing;
import hudson.security.AuthorizationStrategy;
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
import hudson.security.HudsonPrivateSecurityRealm;
import hudson.security.SecurityRealm;
import hudson.model.UpdateCenter.InstallationJob;
import hudson.model.UpdateCenter.UpdateCenterJob;
import hudson.util.VersionNumber;
@@ -98,7 +102,8 @@ public static InstallState getInstallState() {
// Edge case: used Jenkins 1 but did not save the system config page,
// the version is not persisted and returns 1.0, so try to check if
// they actually did anything
if (!Jenkins.getInstance().getItemMap().isEmpty()) {
Jenkins j = Jenkins.getInstance();
if (!j.getItemMap().isEmpty() || !mayBeJenkins2SecurityDefaults(j)) {
return InstallState.UPGRADE;
}
return InstallState.NEW;
@@ -117,6 +122,29 @@ public static InstallState getInstallState() {
}
}

/**
* This could be an upgrade, detect a non-default security realm for the stupid case
* where someone installed 1.x and did not save global config or create any items...
*/
private static boolean mayBeJenkins2SecurityDefaults(Jenkins j) {
if(j.getSecurityRealm() == SecurityRealm.NO_AUTHENTICATION) { // called before security set up first
return true;
}
if(j.getSecurityRealm() instanceof HudsonPrivateSecurityRealm) { // might be called after a restart, setup isn't complete
HudsonPrivateSecurityRealm securityRealm = (HudsonPrivateSecurityRealm)j.getSecurityRealm();
if(securityRealm.getAllUsers().size() == 1 && securityRealm.getUser(SetupWizard.initialSetupAdminUserName) != null) {
AuthorizationStrategy authStrategy = j.getAuthorizationStrategy();
if(authStrategy instanceof FullControlOnceLoggedInAuthorizationStrategy) {
// must have been using 2.0+ to set this, as it wasn't present in 1.x and the default is true, to _allow_ anon read
if(!((FullControlOnceLoggedInAuthorizationStrategy)authStrategy).isAllowAnonymousRead()) {
return true;
}
}
}
}
return false;
}

/**
* Save the current Jenkins instance version as the last executed version.
* <p>
@@ -3,6 +3,7 @@
import java.io.IOException;
import java.util.Locale;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.Filter;
@@ -25,6 +26,7 @@

import hudson.BulkChange;
import hudson.FilePath;
import hudson.model.UpdateCenter;
import hudson.model.User;
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
import hudson.security.HudsonPrivateSecurityRealm;
@@ -55,6 +57,12 @@

public SetupWizard(Jenkins j) throws IOException, InterruptedException {
this.jenkins = j;

// this was determined to be a new install, don't run the update wizard here
UpgradeWizard uw = jenkins.getInjector().getInstance(UpgradeWizard.class);
if (uw!=null)
uw.setCurrentLevel(new VersionNumber("2.0"));

// Create an admin user by default with a
// difficult password
FilePath iapf = getInitialAdminPasswordFile();
@@ -96,29 +104,50 @@ public SetupWizard(Jenkins j) throws IOException, InterruptedException {
}
}

String setupKey = iapf.readToString().trim();
String ls = System.lineSeparator();
LOGGER.info(ls + ls + "*************************************************************" + ls
+ "*************************************************************" + ls
+ "*************************************************************" + ls
+ ls
+ "Jenkins initial setup is required. An admin user has been created and "
+ "a password generated." + ls
+ "Please use the following password to proceed to installation:" + ls
+ ls
+ setupKey + ls
+ ls
+ "This may also be found at: " + iapf.getRemote() + ls
+ ls
+ "*************************************************************" + ls
+ "*************************************************************" + ls
+ "*************************************************************" + ls);
if(iapf.exists()) {
String setupKey = iapf.readToString().trim();
String ls = System.lineSeparator();
LOGGER.info(ls + ls + "*************************************************************" + ls
+ "*************************************************************" + ls
+ "*************************************************************" + ls
+ ls
+ "Jenkins initial setup is required. An admin user has been created and "
+ "a password generated." + ls
+ "Please use the following password to proceed to installation:" + ls
+ ls
+ setupKey + ls
+ ls
+ "This may also be found at: " + iapf.getRemote() + ls
+ ls
+ "*************************************************************" + ls
+ "*************************************************************" + ls
+ "*************************************************************" + ls);
}

try {
PluginServletFilter.addFilter(FORCE_SETUP_WIZARD_FILTER);
} catch (ServletException e) {
throw new AssertionError(e);
}

try {
// Make sure plugin metadata is up to date
UpdateCenter.updateDefaultSite();
} catch (Exception e) {
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
}

/**
* Indicates a generated password should be used - e.g. this is a new install, no security realm set up
*/
public boolean useGeneratedPassword() {
try {
return getInitialAdminPasswordFile().exists();
} catch (Exception e) {
// ignore
}
return false;
}

/**
@@ -143,6 +172,13 @@ public void doCreateAdminUser(StaplerRequest req, StaplerResponse rsp) throws IO
admin = null;
}

// Success! Delete the temporary password file:
try {
getInitialAdminPasswordFile().delete();
} catch (InterruptedException e) {
throw new IOException(e);
}

j.setInstallState(InstallState.CREATE_ADMIN_USER.getNextState());

// ... and then login
@@ -174,10 +210,6 @@ public HttpResponse doCompleteInstall() throws IOException, ServletException {
// Also, clean up the setup wizard if it's completed
jenkins.setSetupWizard(null);

UpgradeWizard uw = jenkins.getInjector().getInstance(UpgradeWizard.class);
if (uw!=null)
uw.setCurrentLevel(new VersionNumber("2.0"));

return HttpResponses.okJSON();
}

@@ -342,7 +342,7 @@
/**
* The Jenkins instance startup type i.e. NEW, UPGRADE etc
*/
private transient InstallState installState = InstallState.NEW;
private transient InstallState installState = InstallState.UNKNOWN;

/**
* If we're in the process of an initial setup,
@@ -810,11 +810,6 @@ protected Jenkins(File root, ServletContext context, PluginManager pluginManager
throw new IllegalStateException("second instance");
theInstance = this;

installState = InstallUtil.getInstallState();
if (installState == InstallState.RESTART || installState == InstallState.DOWNGRADE) {
InstallUtil.saveLastExecVersion();
}

if (!new File(root,"jobs").exists()) {
// if this is a fresh install, use more modern default layout that's consistent with agents
workspaceDir = "${JENKINS_HOME}/workspace/${ITEM_FULLNAME}";
@@ -875,6 +870,11 @@ protected Jenkins(File root, ServletContext context, PluginManager pluginManager
if(KILL_AFTER_LOAD)
System.exit(0);

installState = InstallUtil.getInstallState();
if (installState == InstallState.RESTART || installState == InstallState.DOWNGRADE) {
InstallUtil.saveLastExecVersion();
}

if(!installState.isSetupComplete()) {
// Start immediately with the setup wizard for new installs
setupWizard = new SetupWizard(this);
@@ -24,10 +24,11 @@ THE SOFTWARE.

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<j:if test="${it.setupWizard != null}">
<j:choose>
<j:when test="${it.setupWizard != null and it.setupWizard.useGeneratedPassword()}">
<st:include it="${it.setupWizard}" page="authenticate-security-token"/>
</j:if>
<j:if test="${it.setupWizard == null}">
</j:when>
<j:otherwise>
<l:layout norefresh="true">
<l:hasPermission permission="${app.READ}">
<st:include page="sidepanel.jelly" />
@@ -74,5 +75,6 @@ THE SOFTWARE.
</div>
</l:main-panel>
</l:layout>
</j:if>
</j:otherwise>
</j:choose>
</j:jelly>
@@ -27,7 +27,7 @@ THE SOFTWARE.
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<j:choose>
<j:new var="h" className="hudson.Functions" />
<j:when test="${app.setupWizard != null}">
<j:when test="${app.setupWizard != null and app.setupWizard.useGeneratedPassword()}">
<j:set var="error" value="true"/>
<st:include it="${app.setupWizard}" page="authenticate-security-token"/>
</j:when>

0 comments on commit 37c00cf

Please sign in to comment.
You can’t perform that action at this time.