From ac377cd2ad09c2f1199689f0918d581d1774e52a Mon Sep 17 00:00:00 2001 From: James Nord Date: Thu, 20 Jun 2024 12:18:38 +0100 Subject: [PATCH 1/2] [JENKINS-73334] Block the use of PKCS#12 when in FIPS mode PKCS#12 is not FIPS compliant as such we need to block these certificate uploades when in FIPS mode. --- .../impl/CertificateCredentialsImpl.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/cloudbees/plugins/credentials/impl/CertificateCredentialsImpl.java b/src/main/java/com/cloudbees/plugins/credentials/impl/CertificateCredentialsImpl.java index 3b938c7c4..1c0b72169 100644 --- a/src/main/java/com/cloudbees/plugins/credentials/impl/CertificateCredentialsImpl.java +++ b/src/main/java/com/cloudbees/plugins/credentials/impl/CertificateCredentialsImpl.java @@ -59,6 +59,7 @@ import java.util.logging.Logger; import jenkins.model.Jenkins; +import jenkins.security.FIPS140; import net.jcip.annotations.GuardedBy; import org.apache.commons.fileupload.FileItem; import org.apache.commons.lang.StringUtils; @@ -404,7 +405,7 @@ private Object readResolve() { } /** - * Let the user reference an uploaded file. + * Let the user reference an uploaded PKCS12 file. */ public static class UploadedKeyStoreSource extends KeyStoreSource implements Serializable { /** @@ -435,6 +436,7 @@ public static class UploadedKeyStoreSource extends KeyStoreSource implements Ser @SuppressWarnings("unused") // by stapler @Deprecated public UploadedKeyStoreSource(String uploadedKeystore) { + ensureNotRunningInFIPSMode(); this.uploadedKeystoreBytes = StringUtils.isBlank(uploadedKeystore) ? null : SecretBytes.fromBytes(DescriptorImpl.toByteArray(Secret.fromString(uploadedKeystore))); @@ -449,6 +451,7 @@ public UploadedKeyStoreSource(String uploadedKeystore) { @SuppressWarnings("unused") // by stapler @Deprecated public UploadedKeyStoreSource(@CheckForNull SecretBytes uploadedKeystore) { + ensureNotRunningInFIPSMode(); this.uploadedKeystoreBytes = uploadedKeystore; } @@ -461,6 +464,7 @@ public UploadedKeyStoreSource(@CheckForNull SecretBytes uploadedKeystore) { @SuppressWarnings("unused") // by stapler @DataBoundConstructor public UploadedKeyStoreSource(FileItem uploadedCertFile, @CheckForNull SecretBytes uploadedKeystore) { + ensureNotRunningInFIPSMode(); if (uploadedCertFile != null) { byte[] fileBytes = uploadedCertFile.get(); if (fileBytes.length != 0) { @@ -478,6 +482,7 @@ public UploadedKeyStoreSource(FileItem uploadedCertFile, @CheckForNull SecretByt * @since 2.1.5 */ private Object readResolve() throws ObjectStreamException { + ensureNotRunningInFIPSMode(); if (uploadedKeystore != null && uploadedKeystoreBytes == null) { return new UploadedKeyStoreSource(SecretBytes.fromBytes(DescriptorImpl.toByteArray(uploadedKeystore))); } @@ -526,13 +531,31 @@ public String toString() { return "UploadedKeyStoreSource{uploadedKeystoreBytes=******}"; } + /* + * Prevents the use of any direct usage of the class when running in FIPS mode as PKCS12 is not compliant. + */ + private static void ensureNotRunningInFIPSMode() { + if (FIPS140.useCompliantAlgorithms()) { + throw new IllegalStateException("UploadedKeyStoreSource is not compliant with FIPS-140 and can not be used when Jenkins is in FIPS mode. " + + "This is an error in the calling code and an issue should be filed against the plugin that is calling to adapt to become FIPS compliant."); + } + } + /** * {@inheritDoc} */ - @Extension public static class DescriptorImpl extends KeyStoreSourceDescriptor { public static final String DEFAULT_VALUE = UploadedKeyStoreSource.class.getName() + ".default-value"; + /** + * Creates the extension if we are not in FIPS mode, do NOT call this directly! + */ + @Restricted(NoExternalUse.class) + @Extension + public static DescriptorImpl extension() { + return FIPS140.useCompliantAlgorithms() ? null : new DescriptorImpl(); + } + /** * Decode the {@link Base64} keystore wrapped in a {@link Secret}. * From e3108d285e1e9d4260590883b8bc63bd1221d833 Mon Sep 17 00:00:00 2001 From: James Nord Date: Thu, 20 Jun 2024 14:35:33 +0100 Subject: [PATCH 2/2] leave a (temporary) warning if there are no KeyStoreSources This is expected to be a temporary measure pending JENKINS-73335 as such no tests are introduced for this, rather manual testing was performed. --- .../impl/CertificateCredentialsImpl/credentials.jelly | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/resources/com/cloudbees/plugins/credentials/impl/CertificateCredentialsImpl/credentials.jelly b/src/main/resources/com/cloudbees/plugins/credentials/impl/CertificateCredentialsImpl/credentials.jelly index 5c89dbd7a..5e86264ed 100644 --- a/src/main/resources/com/cloudbees/plugins/credentials/impl/CertificateCredentialsImpl/credentials.jelly +++ b/src/main/resources/com/cloudbees/plugins/credentials/impl/CertificateCredentialsImpl/credentials.jelly @@ -26,7 +26,15 @@ - + + + +
Jenkins has no KeyStoreSources available, Certificate credentials will not be able to be created.
+
+ + + +