-
Notifications
You must be signed in to change notification settings - Fork 696
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-74907] Add validations when Jenkins is in FIPS mode #1010
Open
jmdesprez
wants to merge
27
commits into
jenkinsci:master
Choose a base branch
from
jmdesprez:JENKINS-74907
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
3005143
Bump jenkins version
jmdesprez ab2914f
Add FIPS utility methods and messages
jmdesprez 986fec8
Add FIPS compliance check for WinRM
jmdesprez 986005e
Add FIPS compliance check for WinRMClient
jmdesprez 066106e
Add FIPS compliance check for HostKey
jmdesprez 89b9443
Add FIPS compliance check for EC2Cloud
jmdesprez dff8af1
Add FIPS compliance check for WinConnection
jmdesprez 1729122
Add FIPS compliance check for WindowsData
jmdesprez 6520e9f
Merge branch 'master' into JENKINS-74907
jmdesprez 41419cc
Fix Jenkins security scan
jmdesprez 2f073ac
Align BOM version with Jenkins version
jmdesprez 5877f74
Bump Jenkins
jmdesprez 1bb4a31
Fix tests
jmdesprez 78a96b7
Make use of Common Lang instead of a private method
jmdesprez c16aeaf
Throw FormException instead of IllegalArgumentException
jmdesprez 1fbb826
Make use of FIPS140Utils
jmdesprez e04e639
Move utility methods into FIPS140Utils
jmdesprez fcd7cd2
Add FIPS mention to messages keys
jmdesprez af72912
Merge branch 'master' into JENKINS-74907
jmdesprez 8044460
Format repository with Spotless
jmdesprez fd76311
Update messages keys according to the properties file
jmdesprez 126a1ef
Implement ensurePublicKeyInFipsMode using mina
jmdesprez da58504
Remove the RuntimeException catch
jmdesprez 7e34b30
Add FIPS validation of decoded KeyPair
jmdesprez 276ac81
Code cleanup
jmdesprez 8d87877
Enable tests
jmdesprez 8608cdc
Add Windows password length validation
jmdesprez File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
177 changes: 177 additions & 0 deletions
177
src/main/java/hudson/plugins/ec2/util/FIPS140Utils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package hudson.plugins.ec2.util; | ||
|
||
import edu.umd.cs.findbugs.annotations.NonNull; | ||
import hudson.plugins.ec2.Messages; | ||
import java.io.IOException; | ||
import java.net.URL; | ||
import java.security.Key; | ||
import java.security.UnrecoverableKeyException; | ||
import java.security.interfaces.DSAKey; | ||
import java.security.interfaces.ECKey; | ||
import java.security.interfaces.RSAKey; | ||
import jenkins.bouncycastle.api.PEMEncodable; | ||
import jenkins.security.FIPS140; | ||
import org.apache.commons.lang.StringUtils; | ||
import org.bouncycastle.crypto.params.AsymmetricKeyParameter; | ||
import org.bouncycastle.crypto.params.DSAPublicKeyParameters; | ||
import org.bouncycastle.crypto.params.ECPublicKeyParameters; | ||
import org.bouncycastle.crypto.params.RSAKeyParameters; | ||
import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil; | ||
|
||
/** | ||
* FIPS related utility methods (check Private and Public keys, ...) | ||
*/ | ||
public class FIPS140Utils { | ||
|
||
/** | ||
* Checks if the key is allowed when FIPS mode is requested. | ||
* Allowed key with the following algorithms and sizes: | ||
* <ul> | ||
* <li>DSA with key size >= 2048</li> | ||
* <li>RSA with key size >= 2048</li> | ||
* <li>Elliptic curve (ED25519) with field size >= 224</li> | ||
* </ul> | ||
* If the key is valid and allowed or not in FIPS mode method will just exit. | ||
* If not it will throw an {@link IllegalArgumentException}. | ||
* @param key The key to check. | ||
*/ | ||
public static void ensureKeyInFipsMode(Key key) { | ||
if (!FIPS140.useCompliantAlgorithms()) { | ||
return; | ||
} | ||
if (key instanceof RSAKey) { | ||
if (((RSAKey) key).getModulus().bitLength() < 2048) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_invalidKeySizeInFIPSMode()); | ||
} | ||
} else if (key instanceof DSAKey) { | ||
if (((DSAKey) key).getParams().getP().bitLength() < 2048) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_invalidKeySizeInFIPSMode()); | ||
} | ||
} else if (key instanceof ECKey) { | ||
if (((ECKey) key).getParams().getCurve().getField().getFieldSize() < 224) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_invalidKeySizeECInFIPSMode()); | ||
} | ||
} else { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_keyIsNotApprovedInFIPSMode(key.getAlgorithm())); | ||
} | ||
} | ||
|
||
/** | ||
* Password leak prevention when FIPS mode is requested. If FIPS mode is not requested, this method does nothing. | ||
* Otherwise, ensure that no password can be leaked | ||
* @param url the requested URL | ||
* @param password the password used | ||
* @throws IllegalArgumentException if there is a risk that the password will leak | ||
*/ | ||
public static void ensureNoPasswordLeak(URL url, String password) { | ||
ensureNoPasswordLeak("https".equals(url.getProtocol()), password); | ||
} | ||
|
||
/** | ||
* Password leak prevention when FIPS mode is requested. If FIPS mode is not requested, this method does nothing. | ||
* Otherwise, ensure that no password can be leaked. | ||
* @param useHTTPS is TLS used or not | ||
* @param password the password used | ||
* @throws IllegalArgumentException if there is a risk that the password will leak | ||
*/ | ||
public static void ensureNoPasswordLeak(boolean useHTTPS, String password) { | ||
ensureNoPasswordLeak(useHTTPS, !StringUtils.isEmpty(password)); | ||
} | ||
|
||
/** | ||
* Password leak prevention when FIPS mode is requested. If FIPS mode is not requested, this method does nothing. | ||
* Otherwise, ensure that no password can be leaked. | ||
* @param useHTTPS is TLS used or not | ||
* @param usePassword is a password used | ||
* @throws IllegalArgumentException if there is a risk that the password will leak | ||
*/ | ||
public static void ensureNoPasswordLeak(boolean useHTTPS, boolean usePassword) { | ||
if (FIPS140.useCompliantAlgorithms()) { | ||
if (!useHTTPS && usePassword) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_tlsIsRequiredInFIPSMode()); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Password length check chen FIPS mode is requested. If FIPS mode is not requested, this method does nothing. | ||
* Otherwise, ensure that the password length is at least 14 char long. | ||
* @param password the password to check | ||
* @throws IllegalArgumentException if FIPS mode is requested and the password is too short | ||
*/ | ||
public static void ensurePasswordLength(String password) { | ||
if (FIPS140.useCompliantAlgorithms()) { | ||
if (StringUtils.isBlank(password) || password.length() < 14) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_passwordLengthInFIPSMode()); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Password leak prevention when FIPS mode is requested. If FIPS mode is not requested, this method does nothing. | ||
* Otherwise, ensure that no password can be leaked. | ||
* @param allowSelfSignedCertificate is self-signed certificate allowed | ||
* @throws IllegalArgumentException if FIPS mode is requested and a self-signed certificate is allowed | ||
*/ | ||
public static void ensureNoSelfSignedCertificate(boolean allowSelfSignedCertificate) { | ||
if (FIPS140.useCompliantAlgorithms()) { | ||
if (allowSelfSignedCertificate) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_selfSignedCertificateNotAllowedInFIPSMode()); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Checks if the private key is allowed when FIPS mode is requested. | ||
* Allowed private key with the following algorithms and sizes: | ||
* <ul> | ||
* <li>DSA with key size >= 2048</li> | ||
* <li>RSA with key size >= 2048</li> | ||
* <li>Elliptic curve (ED25519) with field size >= 224</li> | ||
* </ul> | ||
* If the private key is valid and allowed or not in FIPS mode method will just exit. | ||
* If not it will throw an {@link IllegalArgumentException}. | ||
* @param privateKeyString String containing the private key PEM. | ||
*/ | ||
public static void ensurePrivateKeyInFipsMode(String privateKeyString) { | ||
if (!FIPS140.useCompliantAlgorithms()) { | ||
return; | ||
} | ||
if (StringUtils.isBlank(privateKeyString)) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_keyIsMandatoryInFIPSMode()); | ||
} | ||
try { | ||
Key privateKey = PEMEncodable.decode(privateKeyString).toPrivateKey(); | ||
ensureKeyInFipsMode(privateKey); | ||
} catch (RuntimeException | UnrecoverableKeyException | IOException e) { | ||
throw new IllegalArgumentException(e.getMessage(), e); | ||
} | ||
} | ||
|
||
public static void ensurePublicKeyInFipsMode(@NonNull String algorithm, @NonNull byte[] key) { | ||
if (!FIPS140.useCompliantAlgorithms()) { | ||
return; | ||
} | ||
|
||
AsymmetricKeyParameter asymmetricKeyParameter = OpenSSHPublicKeyUtil.parsePublicKey(key); | ||
|
||
if (asymmetricKeyParameter instanceof RSAKeyParameters) { | ||
RSAKeyParameters rsaKeyParameters = (RSAKeyParameters) asymmetricKeyParameter; | ||
if (rsaKeyParameters.getModulus().bitLength() < 2048) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_invalidKeySizeInFIPSMode()); | ||
} | ||
} else if (asymmetricKeyParameter instanceof DSAPublicKeyParameters) { | ||
DSAPublicKeyParameters dsaPublicKeyParameters = (DSAPublicKeyParameters) asymmetricKeyParameter; | ||
if (dsaPublicKeyParameters.getParameters().getP().bitLength() < 2048) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_invalidKeySizeInFIPSMode()); | ||
} | ||
} else if (asymmetricKeyParameter instanceof ECPublicKeyParameters) { | ||
ECPublicKeyParameters ecPublicKeyParameters = (ECPublicKeyParameters) asymmetricKeyParameter; | ||
if (ecPublicKeyParameters.getParameters().getCurve().getFieldSize() < 224) { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_invalidKeySizeECInFIPSMode()); | ||
} | ||
} else { | ||
throw new IllegalArgumentException(Messages.EC2Cloud_keyIsNotApprovedInFIPSMode(algorithm)); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There appears to be no check on the password length here if a password is in used? Also should the checks only take place if
specifyPassword
is true?