From fe5d2664991f63112b1263ad2aa8a349d774d4f1 Mon Sep 17 00:00:00 2001 From: Priya Date: Fri, 13 Dec 2024 18:17:46 +0530 Subject: [PATCH] [JENKINS-74964] Descriptor#newInstanceImpl Linkage error handling test cases --- .../credentials/CredentialsSelectHelper.java | 10 +- .../lib/credentials/select/select.js | 2 +- .../CredentialsSelectHelperTest.java | 129 +++++++++++++++--- 3 files changed, 112 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/cloudbees/plugins/credentials/CredentialsSelectHelper.java b/src/main/java/com/cloudbees/plugins/credentials/CredentialsSelectHelper.java index 2ab53974..978d50ae 100644 --- a/src/main/java/com/cloudbees/plugins/credentials/CredentialsSelectHelper.java +++ b/src/main/java/com/cloudbees/plugins/credentials/CredentialsSelectHelper.java @@ -38,9 +38,9 @@ import hudson.model.User; import hudson.security.AccessControlled; import hudson.security.Permission; -import hudson.util.HttpResponses; import java.io.IOException; +import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -633,17 +633,13 @@ public JSONObject doAddCredentials(StaplerRequest2 req, StaplerResponse2 rsp) th */ Throwable rootCause = ExceptionUtils.getRootCause(e); if (rootCause instanceof IOException || rootCause instanceof IllegalArgumentException - || rootCause instanceof IllegalStateException) { + || rootCause instanceof GeneralSecurityException) { LOGGER.log(Level.WARNING, "Failed to create Credentials", e); return new JSONObject().element("message", rootCause.getMessage()).element("notificationType", "ERROR"); } throw e; - } catch (IOException | IllegalArgumentException | IllegalStateException | - HttpResponses.HttpResponseException e) { - LOGGER.log(Level.WARNING, "Failed to create Credentials", e); - return new JSONObject().element("message", e.getMessage()).element("notificationType", "ERROR"); - } + } if (credentialsWereAdded) { return new JSONObject() .element("message", "Credentials created") diff --git a/src/main/resources/lib/credentials/select/select.js b/src/main/resources/lib/credentials/select/select.js index 932f19e7..f1ef36a6 100644 --- a/src/main/resources/lib/credentials/select/select.js +++ b/src/main/resources/lib/credentials/select/select.js @@ -123,7 +123,7 @@ window.credentials.addSubmit = function (_) { .catch((e) => { // notificationBar.show(...) with logging ID could be handy here? console.error("Could not add credentials:", e); - window.notificationBar.show("Credentials creation failed.", window.notificationBar["ERROR"]); + window.notificationBar.show("Credentials creation failed", window.notificationBar["ERROR"]); }) } }; diff --git a/src/test/java/com/cloudbees/plugins/credentials/CredentialsSelectHelperTest.java b/src/test/java/com/cloudbees/plugins/credentials/CredentialsSelectHelperTest.java index 83eacc6b..3d8c7ec0 100644 --- a/src/test/java/com/cloudbees/plugins/credentials/CredentialsSelectHelperTest.java +++ b/src/test/java/com/cloudbees/plugins/credentials/CredentialsSelectHelperTest.java @@ -7,10 +7,14 @@ import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials; import com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl; +import com.cloudbees.plugins.credentials.impl.CertificateCredentialsImplTest; + import hudson.model.UnprotectedRootAction; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.List; import net.sf.json.JSONObject; +import org.apache.commons.io.IOUtils; import org.hamcrest.Matchers; import org.htmlunit.Page; import org.htmlunit.html.DomNode; @@ -23,6 +27,7 @@ import org.htmlunit.html.HtmlOption; import org.htmlunit.html.HtmlPage; import org.htmlunit.html.HtmlRadioButtonInput; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.Issue; @@ -33,6 +38,21 @@ public class CredentialsSelectHelperTest { @Rule public JenkinsRule j = new JenkinsRule(); + private String pemCert; + private String pemKey; + + private static final String VALID_PASSWORD = "password"; + private static final String INVALID_PASSWORD = "bla"; + + @Before + public void setup() throws IOException { + pemCert = IOUtils.toString(CertificateCredentialsImplTest.class.getResource("certs.pem"), + StandardCharsets.UTF_8); + pemKey = IOUtils.toString(CertificateCredentialsImplTest.class.getResource("key.pem"), + StandardCharsets.UTF_8); + } + + @Test public void doAddCredentialsFromPopupWorksAsExpected() throws Exception { try (JenkinsRule.WebClient wc = j.createWebClient()) { @@ -71,39 +91,106 @@ public void doAddCredentialsFromPopupWorksAsExpected() throws Exception { @Test @Issue("JENKINS-74964") - public void doAddCredentialsFromPopupForInvalidPEMCertificateKeystore() throws Exception { + public void doAddCredentialsFromPopupForPEMCertificateKeystore() throws Exception { try (JenkinsRule.WebClient wc = j.createWebClient()) { HtmlPage htmlPage = wc.goTo("credentials-selection"); + HtmlForm form = selectPEMCertificateKeyStore(htmlPage, wc); + form.getTextAreaByName("_.certChain").setTextContent(pemCert); + form.getTextAreaByName("_.privateKey").setTextContent(pemKey); + form.getInputsByName("_.password").forEach(input -> input.setValue(VALID_PASSWORD)); + Page submit = HtmlFormUtil.submit(form); + JSONObject responseJson = JSONObject.fromObject(submit.getWebResponse().getContentAsString()); + assertThat(responseJson.getString("notificationType"), is("SUCCESS")); + } + } - HtmlButton addCredentialsButton = htmlPage.querySelector(".credentials-add-menu"); - addCredentialsButton.fireEvent("mouseenter"); - addCredentialsButton.click(); + @Test + @Issue("JENKINS-74964") + public void doAddCredentialsFromPopupForPEMCertificateKeystore_missingKeyStore() throws Exception { - HtmlButton jenkinsCredentialsOption = htmlPage.querySelector(".jenkins-dropdown__item"); - jenkinsCredentialsOption.click(); + try (JenkinsRule.WebClient wc = j.createWebClient()) { + HtmlPage htmlPage = wc.goTo("credentials-selection"); + HtmlForm form = selectPEMCertificateKeyStore(htmlPage, wc); + Page submit = HtmlFormUtil.submit(form); + JSONObject responseJson = JSONObject.fromObject(submit.getWebResponse().getContentAsString()); + assertThat(responseJson.getString("notificationType"), is("ERROR")); + } + } - wc.waitForBackgroundJavaScript(4000); - HtmlForm form = htmlPage.querySelector("#credentials-dialog-form"); - String certificateDisplayName = j.jenkins.getDescriptor(CertificateCredentialsImpl.class).getDisplayName(); - String KeyStoreSourceDisplayName = j.jenkins.getDescriptor( - CertificateCredentialsImpl.PEMEntryKeyStoreSource.class).getDisplayName(); - DomNodeList allOptions = htmlPage.getDocumentElement().querySelectorAll( - "select.dropdownList option"); - boolean optionFound = selectOption(allOptions, certificateDisplayName); - assertTrue("The Certificate option was not found in the credentials type select", optionFound); - List inputs = htmlPage.getDocumentElement().getByXPath( - "//input[contains(@name, 'keyStoreSource') and following-sibling::label[contains(.,'" - + KeyStoreSourceDisplayName + "')]]"); - assertThat("query should return only a singular input", inputs, hasSize(1)); - HtmlElementUtil.click(inputs.get(0)); - wc.waitForBackgroundJavaScript(4000); + @Test + @Issue("JENKINS-74964") + public void doAddCredentialsFromPopupForInvalidPEMCertificateKeystore_missingCert() throws Exception { + + try (JenkinsRule.WebClient wc = j.createWebClient()) { + HtmlPage htmlPage = wc.goTo("credentials-selection"); + HtmlForm form = selectPEMCertificateKeyStore(htmlPage, wc); + form.getTextAreaByName("_.certChain").setTextContent(null); + form.getTextAreaByName("_.privateKey").setTextContent(pemKey); + form.getInputsByName("_.password").forEach(input -> input.setValue(VALID_PASSWORD)); + Page submit = HtmlFormUtil.submit(form); + JSONObject responseJson = JSONObject.fromObject(submit.getWebResponse().getContentAsString()); + assertThat(responseJson.getString("notificationType"), is("ERROR")); + } + } + + @Test + @Issue("JENKINS-74964") + public void doAddCredentialsFromPopupForInvalidPEMCertificateKeystore_missingPassword() throws Exception { + + try (JenkinsRule.WebClient wc = j.createWebClient()) { + HtmlPage htmlPage = wc.goTo("credentials-selection"); + HtmlForm form = selectPEMCertificateKeyStore(htmlPage, wc); + form.getTextAreaByName("_.certChain").setTextContent(pemCert); + form.getTextAreaByName("_.privateKey").setTextContent(pemKey); Page submit = HtmlFormUtil.submit(form); JSONObject responseJson = JSONObject.fromObject(submit.getWebResponse().getContentAsString()); assertThat(responseJson.getString("notificationType"), is("ERROR")); } } + @Test + @Issue("JENKINS-74964") + public void doAddCredentialsFromPopupForInvalidPEMCertificateKeystore_invalidPassword() throws Exception { + + try (JenkinsRule.WebClient wc = j.createWebClient()) { + HtmlPage htmlPage = wc.goTo("credentials-selection"); + HtmlForm form = selectPEMCertificateKeyStore(htmlPage, wc); + form.getTextAreaByName("_.certChain").setTextContent(pemCert); + form.getTextAreaByName("_.privateKey").setTextContent(pemKey); + form.getInputsByName("_.password").forEach(input -> input.setValue(INVALID_PASSWORD)); + Page submit = HtmlFormUtil.submit(form); + JSONObject responseJson = JSONObject.fromObject(submit.getWebResponse().getContentAsString()); + assertThat(responseJson.getString("notificationType"), is("ERROR")); + } + } + + private HtmlForm selectPEMCertificateKeyStore(HtmlPage htmlPage, JenkinsRule.WebClient wc) throws IOException { + HtmlButton addCredentialsButton = htmlPage.querySelector(".credentials-add-menu"); + addCredentialsButton.fireEvent("mouseenter"); + addCredentialsButton.click(); + + HtmlButton jenkinsCredentialsOption = htmlPage.querySelector(".jenkins-dropdown__item"); + jenkinsCredentialsOption.click(); + + wc.waitForBackgroundJavaScript(4000); + HtmlForm form = htmlPage.querySelector("#credentials-dialog-form"); + String certificateDisplayName = j.jenkins.getDescriptor(CertificateCredentialsImpl.class).getDisplayName(); + String KeyStoreSourceDisplayName = j.jenkins.getDescriptor( + CertificateCredentialsImpl.PEMEntryKeyStoreSource.class).getDisplayName(); + DomNodeList allOptions = htmlPage.getDocumentElement().querySelectorAll( + "select.dropdownList option"); + boolean optionFound = selectOption(allOptions, certificateDisplayName); + assertTrue("The Certificate option was not found in the credentials type select", optionFound); + List inputs = htmlPage.getDocumentElement().getByXPath( + "//input[contains(@name, 'keyStoreSource') and following-sibling::label[contains(.,'" + + KeyStoreSourceDisplayName + "')]]"); + assertThat("query should return only a singular input", inputs, hasSize(1)); + HtmlElementUtil.click(inputs.get(0)); + wc.waitForBackgroundJavaScript(4000); + return form; + } + private static boolean selectOption(DomNodeList allOptions, String optionName) { return allOptions.stream().anyMatch(domNode -> { if (domNode instanceof HtmlOption option) {