Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-73815] In FiPS mode passwords must be at least 14 characters #314

Merged
merged 2 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/main/java/hudson/tasks/SMTPAuthentication.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@
import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.util.FormValidation;
import hudson.util.Secret;
import jenkins.security.FIPS140;
import org.kohsuke.stapler.DataBoundConstructor;
import hudson.Util;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.interceptor.RequirePOST;

import java.io.ObjectStreamException;

/**
* @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
Expand All @@ -20,6 +26,9 @@
public SMTPAuthentication(String username, Secret password) {
this.username = Util.fixEmptyAndTrim(username);
this.password = password;
if (FIPS140.useCompliantAlgorithms() && Secret.toString(password).length() < 14) {

Check warning on line 29 in src/main/java/hudson/tasks/SMTPAuthentication.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 29 is only partially covered, one branch is missing
throw new IllegalArgumentException(jenkins.plugins.mailer.tasks.i18n.Messages.Mailer_SmtpPassNotFipsCompliant());
}
}

public String getUsername() {
Expand All @@ -30,12 +39,27 @@
return password;
}

private Object readResolve() throws ObjectStreamException {
if (FIPS140.useCompliantAlgorithms() && Secret.toString(password).length() < 14) {

Check warning on line 43 in src/main/java/hudson/tasks/SMTPAuthentication.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 43 is only partially covered, one branch is missing
throw new IllegalStateException("Mailer SMTP password: " + jenkins.plugins.mailer.tasks.i18n.Messages.Mailer_SmtpPassNotFipsCompliant());
}
return this;
}

@Extension
public static class DescriptorImpl extends Descriptor<SMTPAuthentication> {

@Override
public String getDisplayName() {
return "Use SMTP Authentication";
}

@RequirePOST
public FormValidation doCheckPassword(@QueryParameter Secret password) {
alecharp marked this conversation as resolved.
Show resolved Hide resolved
if (FIPS140.useCompliantAlgorithms() && Secret.toString(password).length() < 14) {

Check warning on line 59 in src/main/java/hudson/tasks/SMTPAuthentication.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 59 is only partially covered, one branch is missing
return FormValidation.error(jenkins.plugins.mailer.tasks.i18n.Messages.Mailer_SmtpPassNotFipsCompliant());
}
return FormValidation.ok();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ Mailer.TestMail.Subject=Test email #{0}
Mailer.TestMail.Content=This is test email #{0} sent from {1}
Mailer.InsecureAuthWarning=For security when using authentication it is recommended to enable either TLS or SSL
Mailer.InsecureAuthError=Authentication requires either TLS or SSL to be enabled

Mailer.SmtpPassNotFipsCompliant=When running in FIPS compliance mode, the password must be at least 14 characters long
MailCommand.ShortDescription=\
Reads stdin and sends that out as an e-mail.
108 changes: 108 additions & 0 deletions src/test/java/jenkins/plugins/mailer/FipsModeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package jenkins.plugins.mailer;

import hudson.ExtensionList;
import hudson.diagnosis.OldDataMonitor;
import hudson.tasks.Mailer;
import io.jenkins.plugins.casc.ConfigurationAsCode;
import io.jenkins.plugins.casc.ConfiguratorException;
import org.htmlunit.WebResponse;
import org.htmlunit.html.HtmlForm;
import org.htmlunit.html.HtmlPage;
import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.RealJenkinsRule;
import org.jvnet.hudson.test.recipes.LocalData;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.Serializable;
import java.net.URL;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

public class FipsModeTest {
public static final String SHORT_PWD_ERROR_MESSAGE = "When running in FIPS compliance mode, the password must be at least 14 characters long";
@Rule
public RealJenkinsRule r = new RealJenkinsRule().javaOptions("-Djenkins.security.FIPS140.COMPLIANCE=true").withDebugPort(5008);
alecharp marked this conversation as resolved.
Show resolved Hide resolved

@Test @LocalData
public void testBlowsUpOnStart() throws Throwable {
r.then(FipsModeTest::verifyOldData);
}

static void verifyOldData(JenkinsRule j) throws Throwable {
OldDataMonitor monitor = ExtensionList.lookupSingleton(OldDataMonitor.class);
Mailer.DescriptorImpl descriptor = Mailer.descriptor();
assertNull(descriptor.getAuthentication());
OldDataMonitor.VersionRange versionRange = monitor.getData().get(descriptor);
assertNotNull(versionRange);
assertThat(versionRange.extra, containsString("Mailer SMTP password: " + SHORT_PWD_ERROR_MESSAGE));
}

@Test
public void testConfig() throws Throwable {
r.then(FipsModeTest::_testConfig);
}

public static void _testConfig(JenkinsRule j) throws Exception {
Assume.assumeThat("TODO the form elements for email-ext have the same names", j.getPluginManager().getPlugin("email-ext"), is(nullValue()));

Check warning on line 58 in src/test/java/jenkins/plugins/mailer/FipsModeTest.java

View check run for this annotation

ci.jenkins.io / Open Tasks Scanner

TODO

NORMAL: the form elements for email-ext have the same names", j.getPluginManager().getPlugin("email-ext"), is(nullValue()));
try (JenkinsRule.WebClient wc = j.createWebClient()) {
HtmlPage cp = wc.goTo("configure");
wc.setThrowExceptionOnFailingStatusCode(false);
HtmlForm form = cp.getFormByName("config");

form.getInputByName("_.smtpHost").setValue("acme.com");
form.getInputByName("_.defaultSuffix").setValue("@acme.com");
form.getInputByName("_.authentication").setChecked(true);
form.getInputByName("_.username").setValue("user");
form.getInputByName("_.password").setValue("pass");
wc.waitForBackgroundJavaScript(1000);
assertThat(form.getTextContent(), containsString(SHORT_PWD_ERROR_MESSAGE));
HtmlPage page = j.submit(form);
WebResponse webResponse = page.getWebResponse();
assertNotEquals(200, webResponse.getStatusCode());
assertThat(webResponse.getContentAsString(), containsString(SHORT_PWD_ERROR_MESSAGE));
}

}

@Test @LocalData
public void casc() throws Throwable {
URL url = getClass().getResource("bad_fips_casc.yaml");
r.then(new _casc(url.toString()));
}

public static class _casc implements RealJenkinsRule.Step2<Serializable> {
String resUrl;

public _casc(String resUrl) {
this.resUrl = resUrl;
}

@Override
public Serializable run(JenkinsRule r) throws Throwable {
try {
ConfigurationAsCode.get().configure(resUrl);
fail("The configuration should fail.");
} catch (ConfiguratorException e) {
Throwable cause = e.getCause();
assertNotNull(cause);
cause = cause.getCause();
assertThat(cause, instanceOf(IllegalArgumentException.class));
assertThat(cause.getMessage(), containsString(SHORT_PWD_ERROR_MESSAGE));
}
return null;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ÿ³÷Ħ¶5u£×Mü…§“3|¯ÎöMn+úäª^ØE;š¥jy¡‚­þ›•Ýüö;¶qˆJKMÈJºÌ- mKø£Eï`š¸w´¼T݋„È´yMˆ™GÄ^,ìÃm¾ ª
(˜ ¿gr,Tã̉êÿ‡028WŒÿN ‹2rD™i…EšÆ} sa„=<˜Ó0þÔ ÑC]Sß~àƒ0í—âðŸ¡TÍøQlŸÚ2òª|@ Ö¼€r&[Qé« _]殣‘Kv`ˆ]ҋ šù…¨ÌrŒ0XnŽ„§¾¹½ØS½‰=u‘¥ÛOOdbŠ×–ëoª(™§Z›7㘎¼>0`³|à‚j¨&C
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
8eëJŸVW°ÁêOÙæ2Ët.Ë¿u=Ë
‹
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
98e782a367e04fbffad76f28cc32eb0b7757ff91bd31656cdbcc42a0acf3b92f925b0abf9fbbbd51e7d79bace99d182bb4b337a485b519a73e9089c3e6a78184aeb514731bbb578c205879187411f7e8f709f183c5fdf098155ef56362636c4a5762aa831b6d5d82deb1adfc7f306139e6d480093f639484ecb3f9143bc56097
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version='1.1' encoding='UTF-8'?>
<hudson.tasks.Mailer_-DescriptorImpl plugin="mailer@999999-SNAPSHOT">
<defaultSuffix></defaultSuffix>
<authentication>
<username>smtpusr</username>
<password>{AQAAABAAAAAQcrlS6VKIiJEH44B7K+oxdcs0j4LcZbicOnwQK0Ivlfg=}</password>
</authentication>
<useSsl>true</useSsl>
<useTls>false</useTls>
<charset>UTF-8</charset>
</hudson.tasks.Mailer_-DescriptorImpl>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version='1.1' encoding='UTF-8'?>
<jenkins.model.JenkinsLocationConfiguration>
<adminAddress>address not configured yet &lt;nobody@nowhere&gt;</adminAddress>
<jenkinsUrl>http://localhost:8080/jenkins/</jenkinsUrl>
</jenkins.model.JenkinsLocationConfiguration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ÿ³÷Ħ¶5u£×Mü…§“3|¯ÎöMn+úäª^ØE;š¥jy¡‚­þ›•Ýüö;¶qˆJKMÈJºÌ- mKø£Eï`š¸w´¼T݋„È´yMˆ™GÄ^,ìÃm¾ ª
(˜ ¿gr,Tã̉êÿ‡028WŒÿN ‹2rD™i…EšÆ} sa„=<˜Ó0þÔ ÑC]Sß~àƒ0í—âðŸ¡TÍøQlŸÚ2òª|@ Ö¼€r&[Qé« _]殣‘Kv`ˆ]ҋ šù…¨ÌrŒ0XnŽ„§¾¹½ØS½‰=u‘¥ÛOOdbŠ×–ëoª(™§Z›7㘎¼>0`³|à‚j¨&C
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
8eëJŸVW°ÁêOÙæ2Ët.Ë¿u=Ë
‹
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
98e782a367e04fbffad76f28cc32eb0b7757ff91bd31656cdbcc42a0acf3b92f925b0abf9fbbbd51e7d79bace99d182bb4b337a485b519a73e9089c3e6a78184aeb514731bbb578c205879187411f7e8f709f183c5fdf098155ef56362636c4a5762aa831b6d5d82deb1adfc7f306139e6d480093f639484ecb3f9143bc56097
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
unclassified:
mailer:
authentication:
password: "{AQAAABAAAAAQcrlS6VKIiJEH44B7K+oxdcs0j4LcZbicOnwQK0Ivlfg=}"
username: "smtpusr"
charset: "UTF-8"
useSsl: true
useTls: false