Skip to content

Commit 2ee8907

Browse files
Add test coverage for certificate credentials in SystemCredentialsTest (#2823)
1 parent 1d37a8e commit 2ee8907

4 files changed

Lines changed: 72 additions & 18 deletions

File tree

integrations/src/test/java/io/jenkins/plugins/casc/CredentialsReadmeTest.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public class CredentialsReadmeTest {
5656
+ "PWLXZZQYqsfWIQwvXTEdAkEA2bziyReYAb9fi17alcvwZXGzyyMY8WOGns8NZKcq\n"
5757
+ "INF8D3PDpcCyOvQI/TS3qHYmGyWdHiKCWsgBqE6kyjqpNQ==\n"
5858
+ "-----END RSA PRIVATE KEY-----\n";
59-
public static final String PASSWORD = "password";
59+
public static final String PASSWORD = "123456";
6060
public static final String TEXT = "text";
6161
public static final String ACCESS_KEY = "access-key";
6262
public static final String SECRET_ACCESS_KEY = "secret-access-key";
@@ -143,12 +143,11 @@ public void testGlobalScopedCredentials() throws Exception {
143143
SecretBytes.fromString(Base64.getEncoder().encodeToString(fileContent));
144144
UploadedKeyStoreSource keyStoreSource = (UploadedKeyStoreSource) cert.getKeyStoreSource();
145145
assertThat(keyStoreSource.getUploadedKeystore().getPlainData(), is(secretBytes.getPlainData()));
146-
assertThat(cert.getKeyStore().containsAlias("1"), is(true));
147-
assertThat(cert.getKeyStore().getCertificate("1").getType(), is("X.509"));
146+
assertThat(cert.getKeyStore().containsAlias("test"), is(true));
147+
assertThat(cert.getKeyStore().getCertificate("test").getType(), is("X.509"));
148148
assertThat(
149149
CredentialsNameProvider.name(cert),
150-
is(
151-
"[email protected], CN=pkcs12, O=Fort-Funston, L=SanFrancisco, ST=CA, C=US (my secret cert)"));
150+
is("CN=Test, OU=Jenkins, O=JCasC, L=Delhi, ST=Delhi, C=IN (my secret cert)"));
152151
assertThat(cert.getScope(), is(CredentialsScope.GLOBAL));
153152
}
154153
}

integrations/src/test/java/io/jenkins/plugins/casc/SystemCredentialsTest.java

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,32 @@
33
import static org.hamcrest.MatcherAssert.assertThat;
44
import static org.hamcrest.Matchers.containsString;
55
import static org.hamcrest.Matchers.equalTo;
6+
import static org.hamcrest.Matchers.greaterThan;
67
import static org.hamcrest.Matchers.hasSize;
8+
import static org.hamcrest.Matchers.instanceOf;
79
import static org.hamcrest.Matchers.not;
10+
import static org.hamcrest.Matchers.notNullValue;
811

912
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey;
1013
import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.DirectEntryPrivateKeySource;
1114
import com.cloudbees.plugins.credentials.CredentialsProvider;
1215
import com.cloudbees.plugins.credentials.common.CertificateCredentials;
1316
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
17+
import com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl;
18+
import com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl.UploadedKeyStoreSource;
1419
import hudson.security.ACL;
1520
import io.jenkins.plugins.casc.impl.configurators.DataBoundConfigurator;
1621
import io.jenkins.plugins.casc.misc.ConfiguredWithCode;
1722
import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule;
1823
import io.jenkins.plugins.casc.model.CNode;
24+
import java.net.URL;
25+
import java.nio.file.Files;
26+
import java.nio.file.Paths;
27+
import java.security.KeyStore;
28+
import java.security.cert.X509Certificate;
29+
import java.util.Base64;
1930
import java.util.Collections;
31+
import java.util.Enumeration;
2032
import java.util.List;
2133
import java.util.logging.Level;
2234
import java.util.logging.LogRecord;
@@ -41,7 +53,8 @@ public class SystemCredentialsTest {
4153
public RuleChain chain = RuleChain.outerRule(new EnvironmentVariables()
4254
.set("SUDO_PASSWORD", "1234")
4355
.set("SSH_PRIVATE_KEY", "s3cr3t")
44-
.set("SSH_KEY_PASSWORD", "ABCD"))
56+
.set("SSH_KEY_PASSWORD", "123456")
57+
.set("CERTIFICATE_BASE64", getBase64Keystore()))
4558
.around(log)
4659
.around(new JenkinsConfiguredWithCodeRule());
4760

@@ -63,16 +76,42 @@ public void configure_system_credentials() throws Exception {
6376

6477
List<CertificateCredentials> certs = CredentialsProvider.lookupCredentials(
6578
CertificateCredentials.class, jenkins, ACL.SYSTEM, Collections.emptyList());
66-
assertThat(certs, hasSize(0));
67-
// TODO: add test for uploaded certificate
68-
// assertThat(certs.get(0).getPassword().getPlainText(), equalTo("ABCD"));
79+
assertThat(certs, hasSize(1));
80+
81+
CertificateCredentialsImpl certImpl = (CertificateCredentialsImpl) certs.get(0);
82+
assertThat(certImpl.getId(), equalTo("uploaded_certificate"));
83+
assertThat(certImpl.getPassword().getPlainText(), equalTo("123456"));
84+
assertThat(certImpl.getKeyStoreSource(), notNullValue());
85+
assertThat(certImpl.getKeyStoreSource(), instanceOf(UploadedKeyStoreSource.class));
86+
assertThat(certImpl.getKeyStore(), notNullValue());
87+
assertThat(certImpl.getKeyStore().size(), greaterThan(0));
88+
89+
UploadedKeyStoreSource keyStoreSource = (UploadedKeyStoreSource) certImpl.getKeyStoreSource();
90+
assertThat(keyStoreSource.getUploadedKeystore(), notNullValue());
91+
92+
byte[] expectedBytes = getRawKeystoreBytes();
93+
byte[] actualBytes = keyStoreSource.getUploadedKeystore().getPlainData();
94+
assertThat("The bytes in Jenkins should be identical to the source file", actualBytes, equalTo(expectedBytes));
95+
96+
KeyStore keyStore = certImpl.getKeyStore();
97+
Enumeration<String> aliases = keyStore.aliases();
98+
assertThat("Keystore should not be empty", aliases.hasMoreElements(), equalTo(true));
99+
100+
String alias = aliases.nextElement();
101+
X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias);
102+
assertThat(certificate, notNullValue());
103+
104+
String subject = certificate.getSubjectX500Principal().getName();
105+
assertThat(subject, containsString("CN=Test"));
106+
107+
assertThat(certificate.getType(), equalTo("X.509"));
69108

70109
List<BasicSSHUserPrivateKey> sshPrivateKeys = CredentialsProvider.lookupCredentials(
71110
BasicSSHUserPrivateKey.class, jenkins, ACL.SYSTEM, Collections.emptyList());
72111
assertThat(sshPrivateKeys, hasSize(1));
73112

74113
final BasicSSHUserPrivateKey ssh_with_passphrase = sshPrivateKeys.get(0);
75-
assertThat(ssh_with_passphrase.getPassphrase().getPlainText(), equalTo("ABCD"));
114+
assertThat(ssh_with_passphrase.getPassphrase().getPlainText(), equalTo("123456"));
76115

77116
final DirectEntryPrivateKeySource source =
78117
(DirectEntryPrivateKeySource) ssh_with_passphrase.getPrivateKeySource();
@@ -81,7 +120,23 @@ public void configure_system_credentials() throws Exception {
81120
// credentials should not appear in plain text in log
82121
for (LogRecord logRecord : log.getRecords()) {
83122
assertThat(logRecord.getMessage(), not(containsString("1234")));
84-
assertThat(logRecord.getMessage(), not(containsString("ABCD")));
123+
assertThat(logRecord.getMessage(), not(containsString("123456")));
124+
}
125+
}
126+
127+
private static String getBase64Keystore() {
128+
return Base64.getEncoder().encodeToString(getRawKeystoreBytes());
129+
}
130+
131+
private static byte[] getRawKeystoreBytes() {
132+
try {
133+
URL res = SystemCredentialsTest.class.getResource("test.p12");
134+
if (res == null) {
135+
throw new IllegalStateException("Cannot find test.p12 on classpath");
136+
}
137+
return Files.readAllBytes(Paths.get(res.toURI()));
138+
} catch (Exception e) {
139+
throw new RuntimeException("Failed to read test.p12 from classpath", e);
85140
}
86141
}
87142
}

integrations/src/test/resources/io/jenkins/plugins/casc/SystemCredentialsTest.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ credentials:
1616

1717
# global credentials
1818
- credentials:
19-
# - certificate:
20-
# scope: SYSTEM
21-
# id: ssh_private_key
22-
# password: ${SSH_KEY_PASSWORD}
23-
# keyStoreSource:
24-
# secretBytes:
25-
# keyStoreFile: /docker/secret/id_rsa
19+
- certificate:
20+
scope: SYSTEM
21+
id: uploaded_certificate
22+
password: ${SSH_KEY_PASSWORD}
23+
keyStoreSource:
24+
uploaded:
25+
uploadedKeystore: ${CERTIFICATE_BASE64}
2626
- basicSSHUserPrivateKey:
2727
scope: SYSTEM
2828
id: ssh_with_passphrase_provided
23 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)