Skip to content

Commit e1ef610

Browse files
more test coverage
1 parent 411f5cf commit e1ef610

File tree

3 files changed

+81
-5
lines changed

3 files changed

+81
-5
lines changed

x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/CertGenUtils.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,17 +478,24 @@ public static KeyUsage buildKeyUsage(Collection<String> keyUsages) {
478478
}
479479

480480
int usageBits = 0;
481-
for (String keyUsage : keyUsages) {
482-
Integer keyUsageValue = KEY_USAGE_MAPPINGS.get(keyUsage.trim());
481+
for (String keyUsageName : keyUsages) {
482+
Integer keyUsageValue = findKeyUsageByName(keyUsageName);
483483
if (keyUsageValue == null) {
484-
throw new IllegalArgumentException("Unknown keyUsage: " + keyUsage);
484+
throw new IllegalArgumentException("Unknown keyUsage: " + keyUsageName);
485485
}
486486
usageBits |= keyUsageValue;
487487
}
488488
return new KeyUsage(usageBits);
489489
}
490490

491491
public static boolean isValidKeyUsage(String keyUsage) {
492-
return KEY_USAGE_MAPPINGS.containsKey(keyUsage);
492+
return findKeyUsageByName(keyUsage) != null;
493+
}
494+
495+
private static Integer findKeyUsageByName(String keyUsageName) {
496+
if (keyUsageName == null) {
497+
return null;
498+
}
499+
return KEY_USAGE_MAPPINGS.get(keyUsageName.trim());
493500
}
494501
}

x-pack/plugin/security/cli/src/main/java/org/elasticsearch/xpack/security/cli/HttpCertificateCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484

8585
import static org.elasticsearch.xpack.security.cli.CertGenUtils.buildKeyUsage;
8686
import static org.elasticsearch.xpack.security.cli.CertGenUtils.generateSignedCertificate;
87+
import static org.elasticsearch.xpack.security.cli.CertGenUtils.isValidKeyUsage;
8788

8889
/**
8990
* This command is the "elasticsearch-certutil http" command. It provides a guided process for creating
@@ -1048,7 +1049,7 @@ private static List<String> readKeyUsage(Terminal terminal, List<String> default
10481049
terminal.println("Key usage cannot be empty");
10491050
return null;
10501051
}
1051-
if (CertGenUtils.isValidKeyUsage(keyUsage) == false) {
1052+
if (isValidKeyUsage(keyUsage) == false) {
10521053
terminal.println("Invalid key usage: " + keyUsage);
10531054
terminal.println("The key usage should be one of the following values: ");
10541055
for (String keyUsageName : CertGenUtils.KEY_USAGE_MAPPINGS.keySet()) {

x-pack/plugin/security/cli/src/test/java/org/elasticsearch/xpack/security/cli/CertGenUtilsTests.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.bouncycastle.asn1.x509.GeneralName;
1414
import org.bouncycastle.asn1.x509.GeneralNames;
1515
import org.bouncycastle.asn1.x509.KeyPurposeId;
16+
import org.bouncycastle.asn1.x509.KeyUsage;
1617
import org.elasticsearch.common.network.InetAddresses;
1718
import org.elasticsearch.common.network.NetworkAddress;
1819
import org.elasticsearch.core.SuppressForbidden;
@@ -38,7 +39,11 @@
3839
import javax.security.auth.x500.X500Principal;
3940

4041
import static org.elasticsearch.xpack.security.cli.CertGenUtils.KEY_USAGE_BITS;
42+
import static org.elasticsearch.xpack.security.cli.CertGenUtils.KEY_USAGE_MAPPINGS;
4143
import static org.elasticsearch.xpack.security.cli.CertGenUtils.buildKeyUsage;
44+
import static org.elasticsearch.xpack.security.cli.CertGenUtils.isValidKeyUsage;
45+
import static org.hamcrest.Matchers.containsInAnyOrder;
46+
import static org.hamcrest.Matchers.containsString;
4247
import static org.hamcrest.Matchers.equalTo;
4348
import static org.hamcrest.Matchers.is;
4449
import static org.hamcrest.Matchers.notNullValue;
@@ -190,6 +195,69 @@ public void testIssuerCertSubjectDN() throws Exception {
190195

191196
}
192197

198+
public void testBuildKeyUsage() {
199+
// sanity check that lookup maps are containing the same keyUsage entries
200+
assertThat(KEY_USAGE_BITS.keySet(), containsInAnyOrder(KEY_USAGE_MAPPINGS.keySet().toArray()));
201+
202+
// passing null or empty list of keyUsage names should return null
203+
assertThat(buildKeyUsage(null), is(nullValue()));
204+
assertThat(buildKeyUsage(List.of()), is(nullValue()));
205+
206+
// invalid names should throw IAE
207+
var e = expectThrows(IllegalArgumentException.class, () -> buildKeyUsage(List.of(randomAlphanumericOfLength(5))));
208+
assertThat(e.getMessage(), containsString("Unknown keyUsage"));
209+
210+
{
211+
final List<String> keyUsages = randomNonEmptySubsetOf(KEY_USAGE_MAPPINGS.keySet());
212+
final KeyUsage keyUsage = buildKeyUsage(keyUsages);
213+
for (String usageName : keyUsages) {
214+
final Integer usage = KEY_USAGE_MAPPINGS.get(usageName);
215+
assertThat(" mapping for keyUsage [" + usageName + "] is missing", usage, is(notNullValue()));
216+
assertThat("expected keyUsage [" + usageName + "] to be set in [" + keyUsage + "]", keyUsage.hasUsages(usage), is(true));
217+
}
218+
219+
final Set<String> keyUsagesNotSet = KEY_USAGE_MAPPINGS.keySet()
220+
.stream()
221+
.filter(u -> keyUsages.contains(u) == false)
222+
.collect(Collectors.toSet());
223+
224+
for (String usageName : keyUsagesNotSet) {
225+
final Integer usage = KEY_USAGE_MAPPINGS.get(usageName);
226+
assertThat(" mapping for keyUsage [" + usageName + "] is missing", usage, is(notNullValue()));
227+
assertThat(
228+
"expected keyUsage [" + usageName + "] not to be set in [" + keyUsage + "]",
229+
keyUsage.hasUsages(usage),
230+
is(false)
231+
);
232+
}
233+
234+
}
235+
236+
{
237+
// test that duplicates and whitespaces are ignored
238+
KeyUsage keyUsage = buildKeyUsage(
239+
List.of("digitalSignature ", " nonRepudiation", "\tkeyEncipherment", "keyEncipherment\n")
240+
);
241+
assertThat(keyUsage.hasUsages(KEY_USAGE_MAPPINGS.get("digitalSignature")), is(true));
242+
assertThat(keyUsage.hasUsages(KEY_USAGE_MAPPINGS.get("nonRepudiation")), is(true));
243+
assertThat(keyUsage.hasUsages(KEY_USAGE_MAPPINGS.get("digitalSignature")), is(true));
244+
assertThat(keyUsage.hasUsages(KEY_USAGE_MAPPINGS.get("keyEncipherment")), is(true));
245+
}
246+
}
247+
248+
public void testIsValidKeyUsage() {
249+
assertThat(isValidKeyUsage(randomFrom(KEY_USAGE_MAPPINGS.keySet())), is(true));
250+
assertThat(isValidKeyUsage(randomAlphanumericOfLength(5)), is(false));
251+
252+
// keyUsage names are case-sensitive
253+
assertThat(isValidKeyUsage("DigitalSignature"), is(false));
254+
255+
// white-spaces are ignored
256+
assertThat(isValidKeyUsage("keyAgreement "), is(true));
257+
assertThat(isValidKeyUsage("keyCertSign\n"), is(true));
258+
assertThat(isValidKeyUsage("\tcRLSign "), is(true));
259+
}
260+
193261
public static void assertExpectedKeyUsage(X509Certificate certificate, List<String> expectedKeyUsage) {
194262
final boolean[] keyUsage = certificate.getKeyUsage();
195263
assertThat("Expected " + KEY_USAGE_BITS.size() + " bits for key usage", keyUsage.length, equalTo(KEY_USAGE_BITS.size()));

0 commit comments

Comments
 (0)