Skip to content

Commit

Permalink
in FIPS mode password must have minimum length of 14 characters, this…
Browse files Browse the repository at this point in the history
… is preparing for upgrade of credentials plugin version (#58)

* in FIPS mode password must have minimum length of 14 characters and ugrade of credentials plugin version


---------

Signed-off-by: Olivier Lamy <olamy@apache.org>
  • Loading branch information
olamy authored Sep 18, 2024
1 parent 90a488b commit 03c3053
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 9 deletions.
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@

<spotbugs.effort>Max</spotbugs.effort>
<spotbugs.threshold>Low</spotbugs.threshold>

<hpi.compatibleSinceVersion>190</hpi.compatibleSinceVersion>
</properties>

<dependencies>
Expand All @@ -72,6 +74,7 @@
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>credentials</artifactId>
<version>1378.v81ef4269d764</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
import hudson.Extension;
import hudson.model.Descriptor;
import hudson.util.FormValidation;
import hudson.util.Secret;
import jenkins.security.FIPS140;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpHeaders;
import org.apache.http.NameValuePair;
Expand All @@ -17,6 +21,8 @@
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.interceptor.RequirePOST;

import java.io.IOException;
import java.net.URI;
Expand All @@ -43,7 +49,8 @@ public class OpenShiftBearerTokenCredentialImpl extends UsernamePasswordCredenti
private transient ConcurrentMap<String, Token> tokenCache = new ConcurrentHashMap<>();

@DataBoundConstructor
public OpenShiftBearerTokenCredentialImpl(CredentialsScope scope, String id, String description, String username, String password) {
public OpenShiftBearerTokenCredentialImpl(CredentialsScope scope, String id, String description, String username, String password)
throws Descriptor.FormException {
super(scope, id, description, username, password);
}

Expand Down Expand Up @@ -168,6 +175,15 @@ public static class DescriptorImpl extends BaseStandardCredentialsDescriptor {
public String getDisplayName() {
return "OpenShift Username and Password";
}

@RequirePOST
public FormValidation doCheckPassword(@QueryParameter String password) {
if(FIPS140.useCompliantAlgorithms() && StringUtils.length(password) < 14) {
return FormValidation.error(org.jenkinsci.plugins.kubernetes.credentials.Messages.passwordTooShortFIPS());
}
return FormValidation.ok();
}

}

public static class Token {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#
# The MIT License
#
# Copyright (c) 2011-2013, Olivier Lamy.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
passwordTooShortFIPS=Password is too short (< 14 characters)
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,9 @@ public void unprepareFakeOAuthServer() {
}

@Test
public void ensureFIPSCompliantURIRequest() throws IOException {
OpenShiftBearerTokenCredentialImpl cred;
cred = new OpenShiftBearerTokenCredentialImpl(CredentialsScope.GLOBAL, "id", "description", "username", "password");
public void ensureFIPSCompliantURIRequest() throws Exception {
OpenShiftBearerTokenCredentialImpl cred =
new OpenShiftBearerTokenCredentialImpl(CredentialsScope.GLOBAL, "id", "description", "username", "theaustraliancricketteamisthebest");
try {
cred.getToken(scheme + "://localhost:" + server.getAddress().getPort() + "/valid-response", null, skipTLSVerify);
if (!shouldPass) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ private String getURI() {
}

@Test
public void testValidResponse() throws IOException {
public void testValidResponse() throws Exception {
OpenShiftBearerTokenCredentialImpl t = new OpenShiftBearerTokenCredentialImpl(CredentialsScope.GLOBAL, CREDENTIAL_ID, "sample", USERNAME, PASSWORD);
String token = t.getToken(getURI() + "valid-response", null, true);
assertEquals("1234", token);
}

@Test
public void testMultipleCachedTokens() throws IOException {
public void testMultipleCachedTokens() throws Exception {
OpenShiftBearerTokenCredentialImpl t = new OpenShiftBearerTokenCredentialImpl(CredentialsScope.GLOBAL, CREDENTIAL_ID, "sample", USERNAME, PASSWORD);
String token1 = t.getToken(getURI() + "valid-response", null, true);
String token2 = t.getToken(getURI() + "valid-response2", null, true);
Expand All @@ -70,7 +70,7 @@ public void testMultipleCachedTokens() throws IOException {
}

@Test
public void testBadStatusCode() throws IOException {
public void testBadStatusCode() throws Exception {
expectedEx.expect(IOException.class);
expectedEx.expectMessage("The response from the OAuth server was invalid: The OAuth service didn't respond with a redirection but with '400: Bad Request'");

Expand All @@ -79,7 +79,7 @@ public void testBadStatusCode() throws IOException {
}

@Test
public void testMissingLocation() throws IOException {
public void testMissingLocation() throws Exception {
expectedEx.expect(IOException.class);
expectedEx.expectMessage("The response from the OAuth server was invalid: The OAuth service didn't respond with location header");

Expand All @@ -88,7 +88,7 @@ public void testMissingLocation() throws IOException {
}

@Test
public void testBadLocation() throws IOException {
public void testBadLocation() throws Exception {
expectedEx.expect(IOException.class);
expectedEx.expectMessage("The response from the OAuth server was invalid: The response contained no token");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package org.jenkinsci.plugins.kubernetes.credentials;

import hudson.util.FormValidation;
import jenkins.security.FIPS140;
import org.apache.commons.text.StringEscapeUtils;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.jvnet.hudson.test.FlagRule;

import java.util.Arrays;
import java.util.Collection;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.nullValue;

@RunWith(Parameterized.class)
public class OpenShiftBearerTokenCredentialWithFIPSTest extends AbstractOpenShiftBearerTokenCredentialFIPSTest {
@ClassRule
Expand All @@ -30,4 +37,15 @@ public static Collection<Object[]> parameters() {
{"http", true, false, "TLS and TLS check are mandatory when in FIPS mode"},
});
}

@Test
public void tooShortPassword() throws Exception {
FormValidation formValidation = new OpenShiftBearerTokenCredentialImpl.DescriptorImpl().doCheckPassword("");
assertThat(formValidation.getMessage(), containsString(StringEscapeUtils.escapeHtml4(Messages.passwordTooShortFIPS())));
formValidation = new OpenShiftBearerTokenCredentialImpl.DescriptorImpl().doCheckPassword("tooshort");
assertThat(formValidation.getMessage(), containsString(StringEscapeUtils.escapeHtml4(Messages.passwordTooShortFIPS())));
formValidation = new OpenShiftBearerTokenCredentialImpl.DescriptorImpl().doCheckPassword("theaustraliancricketteamisthebest");
assertThat(formValidation.getMessage(), nullValue());
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package org.jenkinsci.plugins.kubernetes.credentials;

import hudson.util.FormValidation;
import jenkins.security.FIPS140;
import org.apache.commons.text.StringEscapeUtils;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.jvnet.hudson.test.FlagRule;

import java.util.Arrays;
import java.util.Collection;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.nullValue;

@RunWith(Parameterized.class)
public class OpenShiftBearerTokenCredentialWithoutFIPSTest extends AbstractOpenShiftBearerTokenCredentialFIPSTest {
@ClassRule
Expand All @@ -29,4 +36,18 @@ public static Collection<Object[]> parameters() {
{"http", false, true, "Not in FIPS mode, any combination should be valid"},
});
}

/**
* similar test to {@link OpenShiftBearerTokenCredentialWithFIPSTest#tooShortPassword()} but here not in FIPS context
* so it is accepted
*/
@Test
public void tooShortPasswordForFIPS() throws Exception {
FormValidation formValidation = new OpenShiftBearerTokenCredentialImpl.DescriptorImpl().doCheckPassword("");
assertThat(formValidation.getMessage(), nullValue());
formValidation = new OpenShiftBearerTokenCredentialImpl.DescriptorImpl().doCheckPassword("tooshort");
assertThat(formValidation.getMessage(), nullValue());
formValidation = new OpenShiftBearerTokenCredentialImpl.DescriptorImpl().doCheckPassword("theaustraliancricketteamisthebest");
assertThat(formValidation.getMessage(), nullValue());
}
}

0 comments on commit 03c3053

Please sign in to comment.