Skip to content

Commit

Permalink
[JENKINS-73815] In FiPS mode passwords must be at least 14 characters…
Browse files Browse the repository at this point in the history
… long
  • Loading branch information
rsandell committed Sep 27, 2024
1 parent 10a910d commit bcdfd65
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 1 deletion.
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 class SMTPAuthentication extends AbstractDescribableImpl<SMTPAuthenticati
public SMTPAuthentication(String username, Secret password) {
this.username = Util.fixEmptyAndTrim(username);
this.password = password;
if (FIPS140.useCompliantAlgorithms() && (password == null || password.getPlainText().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, 2 branches are missing
throw new IllegalArgumentException(jenkins.plugins.mailer.tasks.i18n.Messages.Mailer_SmtpPassNotFipsCompliant());
}
}

public String getUsername() {
Expand All @@ -30,12 +39,27 @@ public Secret getPassword() {
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) {

Check warning

Code scanning / Jenkins Security Scan

Stapler: Missing permission check Warning

Potential missing permission check in DescriptorImpl#doCheckPassword
if (FIPS140.useCompliantAlgorithms() && (password == null || password.getPlainText().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, 2 branches are 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);

@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.
8 changes: 8 additions & 0 deletions src/test/resources/jenkins/plugins/mailer/bad_fips_casc.yaml
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

0 comments on commit bcdfd65

Please sign in to comment.