diff --git a/README.md b/README.md index e69e309272..5a4524d6ec 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ [![Gitter](https://img.shields.io/gitter/room/jenkinsci/jenkins)](https://app.gitter.im/#/room/#jenkinsci_jenkins:gitter.im) In a nutshell, Jenkins is the leading open-source automation server. -Built with Java, it provides over 1,800 [plugins](https://plugins.jenkins.io/) to support automating virtually anything, +Built with Java, it provides over 2,000 [plugins](https://plugins.jenkins.io/) to support automating virtually anything, so that humans can spend their time doing things machines cannot. # What to Use Jenkins for and When to Use It diff --git a/bom/pom.xml b/bom/pom.xml index f5fb0dad03..dc41dbc0e0 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -41,7 +41,7 @@ THE SOFTWARE. 2.0.0-M2 2.4.21 1.1-jenkins-20250108 - 1942.v708e07325402 + 1948.v0f99403fe86a_ @@ -63,7 +63,7 @@ THE SOFTWARE. org.springframework spring-framework-bom - 6.2.2 + 6.2.3 pom import @@ -287,11 +287,6 @@ THE SOFTWARE. localizer 1.31 - - org.jvnet.robust-http-client - robust-http-client - 1.2 - org.jvnet.winp winp @@ -342,7 +337,7 @@ THE SOFTWARE. commons-logging commons-logging - 1.3.4 + 1.3.5 provided diff --git a/core/pom.xml b/core/pom.xml index 4c49c99bf8..0c9b072e0b 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -325,10 +325,6 @@ THE SOFTWARE. org.jvnet.localizer localizer - - org.jvnet.robust-http-client - robust-http-client - org.jvnet.winp winp diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java index 994f550712..179207d446 100644 --- a/core/src/main/java/hudson/Functions.java +++ b/core/src/main/java/hudson/Functions.java @@ -1993,7 +1993,7 @@ public class Functions { */ public static @CheckForNull String getConsoleUrl(WithConsoleUrl withConsoleUrl) { String consoleUrl = withConsoleUrl.getConsoleUrl(); - return consoleUrl != null ? Stapler.getCurrentRequest().getContextPath() + '/' + consoleUrl : null; + return consoleUrl != null ? Stapler.getCurrentRequest2().getContextPath() + '/' + consoleUrl : null; } /** diff --git a/core/src/main/java/hudson/ProxyConfiguration.java b/core/src/main/java/hudson/ProxyConfiguration.java index cc5b30d956..885b68dec4 100644 --- a/core/src/main/java/hudson/ProxyConfiguration.java +++ b/core/src/main/java/hudson/ProxyConfiguration.java @@ -70,7 +70,6 @@ import jenkins.security.stapler.StaplerAccessibleType; import jenkins.util.JenkinsJVM; import jenkins.util.SystemProperties; import org.jenkinsci.Symbol; -import org.jvnet.robust_http_client.RetryableHttpStream; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; import org.kohsuke.stapler.DataBoundConstructor; @@ -346,10 +345,10 @@ public final class ProxyConfiguration extends AbstractDescribableImpl 0 || cal.get(Calendar.MILLISECOND) > 0) { + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + cal.add(Calendar.MINUTE, 1); + } Calendar twoYearsFuture = (Calendar) cal.clone(); twoYearsFuture.add(Calendar.YEAR, 2); OUTER: @@ -440,6 +445,8 @@ public final class CronTab { * (e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in 2.49 */ public Calendar floor(Calendar cal) { + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); Calendar twoYearsAgo = (Calendar) cal.clone(); twoYearsAgo.add(Calendar.YEAR, -2); diff --git a/core/src/main/java/jenkins/console/ConsoleUrlProvider.java b/core/src/main/java/jenkins/console/ConsoleUrlProvider.java index 9c6080ac02..f779c07e62 100644 --- a/core/src/main/java/jenkins/console/ConsoleUrlProvider.java +++ b/core/src/main/java/jenkins/console/ConsoleUrlProvider.java @@ -80,7 +80,7 @@ public interface ConsoleUrlProvider extends Describable { * @return the URL for the console for the specified build, relative to the web server root */ static @NonNull String getRedirectUrl(Run run) { - return Stapler.getCurrentRequest().getContextPath() + '/' + run.getConsoleUrl(); + return Stapler.getCurrentRequest2().getContextPath() + '/' + run.getConsoleUrl(); } static List all() { diff --git a/core/src/main/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfiguration.java b/core/src/main/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfiguration.java index 46d760fe8e..9766cd9772 100644 --- a/core/src/main/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfiguration.java +++ b/core/src/main/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfiguration.java @@ -6,7 +6,7 @@ import java.util.logging.Logger; import net.sf.json.JSONException; import net.sf.json.JSONObject; import org.jenkinsci.Symbol; -import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; /** * Configures check interval for computer retention. @@ -56,7 +56,7 @@ public class GlobalComputerRetentionCheckIntervalConfiguration extends GlobalCon } @Override - public boolean configure(StaplerRequest req, JSONObject json) throws FormException { + public boolean configure(StaplerRequest2 req, JSONObject json) throws FormException { try { final int interval = json.getInt("computerRetentionCheckInterval"); setComputerRetentionCheckInterval(interval); diff --git a/core/src/main/java/jenkins/model/GlobalConfiguration.java b/core/src/main/java/jenkins/model/GlobalConfiguration.java index af788945b2..bc0d700403 100644 --- a/core/src/main/java/jenkins/model/GlobalConfiguration.java +++ b/core/src/main/java/jenkins/model/GlobalConfiguration.java @@ -67,7 +67,7 @@ public abstract class GlobalConfiguration extends Descriptor + * The master key is stored by default in $JENKINS_HOME/secrets/master.key but another location can be provided using the system property jenkins.master.key.file. + *

+ * It is also possible to prevent the generation of the master key file using the system property -Djenkins.master.key.readOnly. In this case, the master key file must be provided or startup will fail. * * @author Kohsuke Kawaguchi */ // @MetaInfServices --- not annotated because this is the fallback implementation public class DefaultConfidentialStore extends ConfidentialStore { + static final String MASTER_KEY_FILE_SYSTEM_PROPERTY = DefaultConfidentialStore.class.getName() + ".file"; + static final String MASTER_KEY_READONLY_SYSTEM_PROPERTY_NAME = DefaultConfidentialStore.class.getName() + ".readOnly"; + private final SecureRandom sr = new SecureRandom(); + @NonNull + private static File getMasterKeyFile(File rootDir) { + var jenkinsMasterKey = SystemProperties.getString(MASTER_KEY_FILE_SYSTEM_PROPERTY); + if (jenkinsMasterKey != null) { + return new File(jenkinsMasterKey); + } else { + return new File(rootDir, "master.key"); + } + } + /** * Directory that stores individual keys. */ @@ -51,6 +68,10 @@ public class DefaultConfidentialStore extends ConfidentialStore { } public DefaultConfidentialStore(File rootDir) throws IOException, InterruptedException { + this(rootDir, getMasterKeyFile(rootDir)); + } + + protected DefaultConfidentialStore(File rootDir, File keyFile) throws IOException, InterruptedException { this.rootDir = rootDir; if (rootDir.mkdirs()) { // protect this directory. but don't change the permission of the existing directory @@ -58,11 +79,15 @@ public class DefaultConfidentialStore extends ConfidentialStore { new FilePath(rootDir).chmod(0700); } - TextFile masterSecret = new TextFile(new File(rootDir, "master.key")); + TextFile masterSecret = new TextFile(keyFile); if (!masterSecret.exists()) { - // we are only going to use small number of bits (since export control limits AES key length) - // but let's generate a long enough key anyway - masterSecret.write(Util.toHexString(randomBytes(128))); + if (SystemProperties.getBoolean(MASTER_KEY_READONLY_SYSTEM_PROPERTY_NAME)) { + throw new IOException(masterSecret + " does not exist and system property " + MASTER_KEY_READONLY_SYSTEM_PROPERTY_NAME + " is set. You must provide a valid master key file."); + } else { + // we are only going to use small number of bits (since export control limits AES key length) + // but let's generate a long enough key anyway + masterSecret.write(Util.toHexString(randomBytes(128))); + } } this.masterKey = Util.toAes128Key(masterSecret.readTrim()); } diff --git a/core/src/main/java/jenkins/security/seed/UserSeedProperty.java b/core/src/main/java/jenkins/security/seed/UserSeedProperty.java index 968ee9320f..17d9dd4335 100644 --- a/core/src/main/java/jenkins/security/seed/UserSeedProperty.java +++ b/core/src/main/java/jenkins/security/seed/UserSeedProperty.java @@ -28,6 +28,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.BulkChange; import hudson.Extension; +import hudson.Util; import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; @@ -39,7 +40,6 @@ import java.util.Objects; import jenkins.model.Jenkins; import jenkins.security.LastGrantedAuthoritiesProperty; import jenkins.util.SystemProperties; -import org.apache.commons.codec.binary.Hex; import org.jenkinsci.Symbol; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.DoNotUse; @@ -103,7 +103,7 @@ public class UserSeedProperty extends UserProperty { byte[] bytes = new byte[SEED_NUM_BYTES]; while (Objects.equals(newSeed, currentSeed)) { RANDOM.nextBytes(bytes); - newSeed = new String(Hex.encodeHex(bytes)); + newSeed = Util.toHexString(bytes); } this.seed = newSeed; } diff --git a/core/src/main/java/jenkins/telemetry/Telemetry.java b/core/src/main/java/jenkins/telemetry/Telemetry.java index de081c1695..968ca0f08d 100644 --- a/core/src/main/java/jenkins/telemetry/Telemetry.java +++ b/core/src/main/java/jenkins/telemetry/Telemetry.java @@ -32,6 +32,7 @@ import hudson.ExtensionList; import hudson.ExtensionPoint; import hudson.PluginWrapper; import hudson.ProxyConfiguration; +import hudson.Util; import hudson.model.AsyncPeriodicWork; import hudson.model.TaskListener; import hudson.model.UsageStatistics; @@ -51,7 +52,6 @@ import java.util.logging.Logger; import jenkins.model.Jenkins; import jenkins.util.SystemProperties; import net.sf.json.JSONObject; -import org.apache.commons.codec.digest.DigestUtils; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -221,7 +221,7 @@ public abstract class Telemetry implements ExtensionPoint { wrappedData.put("type", telemetry.getId()); wrappedData.put("payload", data); String correlationId = ExtensionList.lookupSingleton(Correlator.class).getCorrelationId(); - wrappedData.put("correlator", DigestUtils.sha256Hex(correlationId + telemetry.getId())); + wrappedData.put("correlator", Util.getHexOfSHA256DigestOf(correlationId + telemetry.getId())); String body = wrappedData.toString(); if (LOGGER.isLoggable(Level.FINEST)) { diff --git a/core/src/main/java/jenkins/util/JSONSignatureValidator.java b/core/src/main/java/jenkins/util/JSONSignatureValidator.java index e6f5429f43..d3f416a91f 100644 --- a/core/src/main/java/jenkins/util/JSONSignatureValidator.java +++ b/core/src/main/java/jenkins/util/JSONSignatureValidator.java @@ -1,6 +1,7 @@ package jenkins.util; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import hudson.Util; import hudson.util.FormValidation; import java.io.ByteArrayInputStream; import java.io.File; @@ -33,8 +34,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import jenkins.model.Jenkins; import net.sf.json.JSONObject; -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.binary.Hex; import org.apache.commons.io.output.TeeOutputStream; import org.jvnet.hudson.crypto.CertificateUtil; import org.jvnet.hudson.crypto.SignatureOutputStream; @@ -221,10 +220,10 @@ public class JSONSignatureValidator { // This approach might look unnecessarily clever, but short of having redundant Signature instances, // there doesn't seem to be a better approach for this. try { - if (signature.verify(Hex.decodeHex(providedSignature.toCharArray()))) { + if (signature.verify(Util.fromHexString(providedSignature))) { return true; } - } catch (SignatureException | DecoderException ignore) { + } catch (SignatureException | IllegalArgumentException ignore) { // ignore } @@ -242,7 +241,7 @@ public class JSONSignatureValidator { * Utility method supporting both possible digest formats: Base64 and Hex */ private boolean digestMatches(byte[] digest, String providedDigest) { - return providedDigest.equalsIgnoreCase(Hex.encodeHexString(digest)) || providedDigest.equalsIgnoreCase(Base64.getEncoder().encodeToString(digest)); + return providedDigest.equalsIgnoreCase(Util.toHexString(digest)) || providedDigest.equalsIgnoreCase(Base64.getEncoder().encodeToString(digest)); } diff --git a/core/src/main/resources/META-INF/web-fragment.xml b/core/src/main/resources/META-INF/web-fragment.xml new file mode 100644 index 0000000000..c9acb6e151 --- /dev/null +++ b/core/src/main/resources/META-INF/web-fragment.xml @@ -0,0 +1,279 @@ + + + + + jenkins + + + Stapler + org.kohsuke.stapler.Stapler + + default-encodings + text/html=UTF-8 + + + diagnosticThreadName + false + + true + + + + Stapler + /* + + + + suspicious-request-filter + jenkins.security.SuspiciousRequestFilter + true + + + diagnostic-name-filter + org.kohsuke.stapler.DiagnosticThreadNameFilter + true + + + encoding-filter + hudson.util.CharacterEncodingFilter + true + + + uncaught-exception-filter + org.kohsuke.stapler.UncaughtExceptionFilter + true + + + authentication-filter + hudson.security.HudsonFilter + true + + + csrf-filter + hudson.security.csrf.CrumbFilter + true + + + error-attribute-filter + jenkins.ErrorAttributeFilter + true + + + plugins-filter + hudson.util.PluginServletFilter + true + + + + + + suspicious-request-filter + /* + + + diagnostic-name-filter + /* + + + encoding-filter + /* + + + uncaught-exception-filter + /* + + + authentication-filter + /* + + + csrf-filter + /* + + + error-attribute-filter + /* + + + plugins-filter + /* + + + + + jenkins.util.SystemProperties$Listener + + + hudson.WebAppMain + + + jenkins.JenkinsHttpSessionListener + + + + + admin + + + user + + + hudson + + + + + Hudson + /loginEntry + + + + ** + + + + + + + Disable TRACE + /* + TRACE + + + + + + + other + /* + + + + + + FORM + + /login + /loginError + + + + + + xml + application/xml + + + + log + text/plain + + + war + application/octet-stream + + + ear + application/octet-stream + + + rar + application/octet-stream + + + webm + video/webm + + + + java.lang.Throwable + /oops + + + 404 + /404 + + + + + + true + + + + diff --git a/core/src/main/resources/hudson/PluginManager/available.jelly b/core/src/main/resources/hudson/PluginManager/available.jelly index bfe5b36aaf..73e095bd01 100644 --- a/core/src/main/resources/hudson/PluginManager/available.jelly +++ b/core/src/main/resources/hudson/PluginManager/available.jelly @@ -38,7 +38,7 @@ THE SOFTWARE. placeholder="${%Search available plugins}" id="filter-box" autofocus="true" - value="${request.getParameter('filter')}" /> + value="${request2.getParameter('filter')}" />

diff --git a/core/src/main/resources/hudson/PluginManager/installed.jelly b/core/src/main/resources/hudson/PluginManager/installed.jelly index c9b7dd93f2..81b175b955 100644 --- a/core/src/main/resources/hudson/PluginManager/installed.jelly +++ b/core/src/main/resources/hudson/PluginManager/installed.jelly @@ -43,7 +43,7 @@ THE SOFTWARE. placeholder="${%Search installed plugins}" id="filter-box" autofocus="true" - value="${request.getParameter('filter')}" + value="${request2.getParameter('filter')}" enabled="${!noPlugins}" />
diff --git a/core/src/main/resources/hudson/PluginManager/updates.jelly b/core/src/main/resources/hudson/PluginManager/updates.jelly index d4163fb7cf..5ce8a810ff 100644 --- a/core/src/main/resources/hudson/PluginManager/updates.jelly +++ b/core/src/main/resources/hudson/PluginManager/updates.jelly @@ -41,7 +41,7 @@ THE SOFTWARE. placeholder="${%Search plugin updates}" id="filter-box" autofocus="true" - value="${request.getParameter('filter')}" + value="${request2.getParameter('filter')}" enabled="${!empty(list)}" />
diff --git a/core/src/main/resources/hudson/diagnosis/MemoryUsageMonitor/index.jelly b/core/src/main/resources/hudson/diagnosis/MemoryUsageMonitor/index.jelly index bb0efd378e..43c579130a 100644 --- a/core/src/main/resources/hudson/diagnosis/MemoryUsageMonitor/index.jelly +++ b/core/src/main/resources/hudson/diagnosis/MemoryUsageMonitor/index.jelly @@ -31,7 +31,7 @@ THE SOFTWARE.

${%JVM Memory Usage}

- +
${%Timespan}: diff --git a/core/src/main/resources/hudson/model/AbstractModelObject/descriptionForm.jelly b/core/src/main/resources/hudson/model/AbstractModelObject/descriptionForm.jelly index 633e67f356..b1754861c0 100644 --- a/core/src/main/resources/hudson/model/AbstractModelObject/descriptionForm.jelly +++ b/core/src/main/resources/hudson/model/AbstractModelObject/descriptionForm.jelly @@ -30,14 +30,14 @@ THE SOFTWARE. - + - +
diff --git a/core/src/main/resources/hudson/model/AbstractProject/changes.jelly b/core/src/main/resources/hudson/model/AbstractProject/changes.jelly index bc2ad59d22..dd6ec243a7 100644 --- a/core/src/main/resources/hudson/model/AbstractProject/changes.jelly +++ b/core/src/main/resources/hudson/model/AbstractProject/changes.jelly @@ -31,8 +31,8 @@ THE SOFTWARE. - - + +

diff --git a/core/src/main/resources/hudson/model/AllView/noJob.groovy b/core/src/main/resources/hudson/model/AllView/noJob.groovy index f62125fed9..6a9e355d30 100644 --- a/core/src/main/resources/hudson/model/AllView/noJob.groovy +++ b/core/src/main/resources/hudson/model/AllView/noJob.groovy @@ -111,7 +111,7 @@ div { section(class: "empty-state-section") { ul(class: "empty-state-section-list") { li(class: "content-block") { - a(href: "${rootURL}/${app.securityRealm.loginUrl}?from=${request.requestURI}", + a(href: "${rootURL}/${app.securityRealm.loginUrl}?from=${request2.requestURI}", class: "content-block__link") { span(_("Log in to Jenkins")) span(class: "trailing-icon") { diff --git a/core/src/main/resources/hudson/model/ComputerSet/_new.jelly b/core/src/main/resources/hudson/model/ComputerSet/_new.jelly index 36e2f23fd7..5d3a79782e 100644 --- a/core/src/main/resources/hudson/model/ComputerSet/_new.jelly +++ b/core/src/main/resources/hudson/model/ComputerSet/_new.jelly @@ -32,7 +32,7 @@ THE SOFTWARE. - + @@ -40,7 +40,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/hudson/model/ParametersAction/index.jelly b/core/src/main/resources/hudson/model/ParametersAction/index.jelly index a035793cfa..c8e8bf3aaf 100644 --- a/core/src/main/resources/hudson/model/ParametersAction/index.jelly +++ b/core/src/main/resources/hudson/model/ParametersAction/index.jelly @@ -30,7 +30,7 @@ THE SOFTWARE. - + ${title} diff --git a/core/src/main/resources/hudson/model/ParametersDefinitionProperty/index.jelly b/core/src/main/resources/hudson/model/ParametersDefinitionProperty/index.jelly index 1302960c1a..0bea62baf0 100644 --- a/core/src/main/resources/hudson/model/ParametersDefinitionProperty/index.jelly +++ b/core/src/main/resources/hudson/model/ParametersDefinitionProperty/index.jelly @@ -40,7 +40,7 @@ THE SOFTWARE.

${it.job.pronoun} ${it.job.displayName}

${%description}

- + diff --git a/core/src/main/resources/hudson/model/Run/delete-retry.jelly b/core/src/main/resources/hudson/model/Run/delete-retry.jelly index 79dfa6beed..5e405e5284 100644 --- a/core/src/main/resources/hudson/model/Run/delete-retry.jelly +++ b/core/src/main/resources/hudson/model/Run/delete-retry.jelly @@ -20,7 +20,7 @@

diff --git a/core/src/main/resources/hudson/model/View/index.jelly b/core/src/main/resources/hudson/model/View/index.jelly index 14632b8e60..661e2e22ce 100644 --- a/core/src/main/resources/hudson/model/View/index.jelly +++ b/core/src/main/resources/hudson/model/View/index.jelly @@ -44,7 +44,7 @@ THE SOFTWARE. -