diff --git a/integrations/src/test/java/io/jenkins/plugins/casc/CredentialsReadmeTest.java b/integrations/src/test/java/io/jenkins/plugins/casc/CredentialsReadmeTest.java index 21692b3fcd..f320d8641d 100644 --- a/integrations/src/test/java/io/jenkins/plugins/casc/CredentialsReadmeTest.java +++ b/integrations/src/test/java/io/jenkins/plugins/casc/CredentialsReadmeTest.java @@ -56,7 +56,7 @@ public class CredentialsReadmeTest { + "PWLXZZQYqsfWIQwvXTEdAkEA2bziyReYAb9fi17alcvwZXGzyyMY8WOGns8NZKcq\n" + "INF8D3PDpcCyOvQI/TS3qHYmGyWdHiKCWsgBqE6kyjqpNQ==\n" + "-----END RSA PRIVATE KEY-----\n"; - public static final String PASSWORD = "password"; + public static final String PASSWORD = "123456"; public static final String TEXT = "text"; public static final String ACCESS_KEY = "access-key"; public static final String SECRET_ACCESS_KEY = "secret-access-key"; @@ -143,12 +143,11 @@ public void testGlobalScopedCredentials() throws Exception { SecretBytes.fromString(Base64.getEncoder().encodeToString(fileContent)); UploadedKeyStoreSource keyStoreSource = (UploadedKeyStoreSource) cert.getKeyStoreSource(); assertThat(keyStoreSource.getUploadedKeystore().getPlainData(), is(secretBytes.getPlainData())); - assertThat(cert.getKeyStore().containsAlias("1"), is(true)); - assertThat(cert.getKeyStore().getCertificate("1").getType(), is("X.509")); + assertThat(cert.getKeyStore().containsAlias("test"), is(true)); + assertThat(cert.getKeyStore().getCertificate("test").getType(), is("X.509")); assertThat( CredentialsNameProvider.name(cert), - is( - "EMAILADDRESS=me@myhost.mydomain, CN=pkcs12, O=Fort-Funston, L=SanFrancisco, ST=CA, C=US (my secret cert)")); + is("CN=Test, OU=Jenkins, O=JCasC, L=Delhi, ST=Delhi, C=IN (my secret cert)")); assertThat(cert.getScope(), is(CredentialsScope.GLOBAL)); } } diff --git a/integrations/src/test/java/io/jenkins/plugins/casc/SystemCredentialsTest.java b/integrations/src/test/java/io/jenkins/plugins/casc/SystemCredentialsTest.java index de521a1161..be9a712c43 100644 --- a/integrations/src/test/java/io/jenkins/plugins/casc/SystemCredentialsTest.java +++ b/integrations/src/test/java/io/jenkins/plugins/casc/SystemCredentialsTest.java @@ -3,20 +3,32 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey; import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.DirectEntryPrivateKeySource; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.common.CertificateCredentials; import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials; +import com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl; +import com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl.UploadedKeyStoreSource; import hudson.security.ACL; import io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator; import io.jenkins.plugins.casc.misc.ConfiguredWithCode; import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule; import io.jenkins.plugins.casc.model.CNode; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.cert.X509Certificate; +import java.util.Base64; import java.util.Collections; +import java.util.Enumeration; import java.util.List; import java.util.logging.Level; import java.util.logging.LogRecord; @@ -41,7 +53,8 @@ public class SystemCredentialsTest { public RuleChain chain = RuleChain.outerRule(new EnvironmentVariables() .set("SUDO_PASSWORD", "1234") .set("SSH_PRIVATE_KEY", "s3cr3t") - .set("SSH_KEY_PASSWORD", "ABCD")) + .set("SSH_KEY_PASSWORD", "123456") + .set("CERTIFICATE_BASE64", getBase64Keystore())) .around(log) .around(new JenkinsConfiguredWithCodeRule()); @@ -63,16 +76,42 @@ public void configure_system_credentials() throws Exception { List certs = CredentialsProvider.lookupCredentials( CertificateCredentials.class, jenkins, ACL.SYSTEM, Collections.emptyList()); - assertThat(certs, hasSize(0)); - // TODO: add test for uploaded certificate - // assertThat(certs.get(0).getPassword().getPlainText(), equalTo("ABCD")); + assertThat(certs, hasSize(1)); + + CertificateCredentialsImpl certImpl = (CertificateCredentialsImpl) certs.get(0); + assertThat(certImpl.getId(), equalTo("uploaded_certificate")); + assertThat(certImpl.getPassword().getPlainText(), equalTo("123456")); + assertThat(certImpl.getKeyStoreSource(), notNullValue()); + assertThat(certImpl.getKeyStoreSource(), instanceOf(UploadedKeyStoreSource.class)); + assertThat(certImpl.getKeyStore(), notNullValue()); + assertThat(certImpl.getKeyStore().size(), greaterThan(0)); + + UploadedKeyStoreSource keyStoreSource = (UploadedKeyStoreSource) certImpl.getKeyStoreSource(); + assertThat(keyStoreSource.getUploadedKeystore(), notNullValue()); + + byte[] expectedBytes = getRawKeystoreBytes(); + byte[] actualBytes = keyStoreSource.getUploadedKeystore().getPlainData(); + assertThat("The bytes in Jenkins should be identical to the source file", actualBytes, equalTo(expectedBytes)); + + KeyStore keyStore = certImpl.getKeyStore(); + Enumeration aliases = keyStore.aliases(); + assertThat("Keystore should not be empty", aliases.hasMoreElements(), equalTo(true)); + + String alias = aliases.nextElement(); + X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias); + assertThat(certificate, notNullValue()); + + String subject = certificate.getSubjectX500Principal().getName(); + assertThat(subject, containsString("CN=Test")); + + assertThat(certificate.getType(), equalTo("X.509")); List sshPrivateKeys = CredentialsProvider.lookupCredentials( BasicSSHUserPrivateKey.class, jenkins, ACL.SYSTEM, Collections.emptyList()); assertThat(sshPrivateKeys, hasSize(1)); final BasicSSHUserPrivateKey ssh_with_passphrase = sshPrivateKeys.get(0); - assertThat(ssh_with_passphrase.getPassphrase().getPlainText(), equalTo("ABCD")); + assertThat(ssh_with_passphrase.getPassphrase().getPlainText(), equalTo("123456")); final DirectEntryPrivateKeySource source = (DirectEntryPrivateKeySource) ssh_with_passphrase.getPrivateKeySource(); @@ -81,7 +120,23 @@ public void configure_system_credentials() throws Exception { // credentials should not appear in plain text in log for (LogRecord logRecord : log.getRecords()) { assertThat(logRecord.getMessage(), not(containsString("1234"))); - assertThat(logRecord.getMessage(), not(containsString("ABCD"))); + assertThat(logRecord.getMessage(), not(containsString("123456"))); + } + } + + private static String getBase64Keystore() { + return Base64.getEncoder().encodeToString(getRawKeystoreBytes()); + } + + private static byte[] getRawKeystoreBytes() { + try { + URL res = SystemCredentialsTest.class.getResource("test.p12"); + if (res == null) { + throw new IllegalStateException("Cannot find test.p12 on classpath"); + } + return Files.readAllBytes(Paths.get(res.toURI())); + } catch (Exception e) { + throw new RuntimeException("Failed to read test.p12 from classpath", e); } } } diff --git a/integrations/src/test/resources/io/jenkins/plugins/casc/SystemCredentialsTest.yml b/integrations/src/test/resources/io/jenkins/plugins/casc/SystemCredentialsTest.yml index 8ac47a4522..805c2c8d77 100644 --- a/integrations/src/test/resources/io/jenkins/plugins/casc/SystemCredentialsTest.yml +++ b/integrations/src/test/resources/io/jenkins/plugins/casc/SystemCredentialsTest.yml @@ -16,13 +16,13 @@ credentials: # global credentials - credentials: -# - certificate: -# scope: SYSTEM -# id: ssh_private_key -# password: ${SSH_KEY_PASSWORD} -# keyStoreSource: -# secretBytes: -# keyStoreFile: /docker/secret/id_rsa + - certificate: + scope: SYSTEM + id: uploaded_certificate + password: ${SSH_KEY_PASSWORD} + keyStoreSource: + uploaded: + uploadedKeystore: ${CERTIFICATE_BASE64} - basicSSHUserPrivateKey: scope: SYSTEM id: ssh_with_passphrase_provided diff --git a/integrations/src/test/resources/io/jenkins/plugins/casc/test.p12 b/integrations/src/test/resources/io/jenkins/plugins/casc/test.p12 index 253d4081a3..6c09c5a292 100644 Binary files a/integrations/src/test/resources/io/jenkins/plugins/casc/test.p12 and b/integrations/src/test/resources/io/jenkins/plugins/casc/test.p12 differ