|
13 | 13 | import org.bouncycastle.asn1.x509.GeneralName; |
14 | 14 | import org.bouncycastle.asn1.x509.GeneralNames; |
15 | 15 | import org.bouncycastle.asn1.x509.KeyPurposeId; |
| 16 | +import org.bouncycastle.asn1.x509.KeyUsage; |
16 | 17 | import org.elasticsearch.common.network.InetAddresses; |
17 | 18 | import org.elasticsearch.common.network.NetworkAddress; |
18 | 19 | import org.elasticsearch.core.SuppressForbidden; |
|
38 | 39 | import javax.security.auth.x500.X500Principal; |
39 | 40 |
|
40 | 41 | import static org.elasticsearch.xpack.security.cli.CertGenUtils.KEY_USAGE_BITS; |
| 42 | +import static org.elasticsearch.xpack.security.cli.CertGenUtils.KEY_USAGE_MAPPINGS; |
41 | 43 | 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; |
42 | 47 | import static org.hamcrest.Matchers.equalTo; |
43 | 48 | import static org.hamcrest.Matchers.is; |
44 | 49 | import static org.hamcrest.Matchers.notNullValue; |
@@ -190,6 +195,69 @@ public void testIssuerCertSubjectDN() throws Exception { |
190 | 195 |
|
191 | 196 | } |
192 | 197 |
|
| 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 | + |
193 | 261 | public static void assertExpectedKeyUsage(X509Certificate certificate, List<String> expectedKeyUsage) { |
194 | 262 | final boolean[] keyUsage = certificate.getKeyUsage(); |
195 | 263 | assertThat("Expected " + KEY_USAGE_BITS.size() + " bits for key usage", keyUsage.length, equalTo(KEY_USAGE_BITS.size())); |
|
0 commit comments