001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.io.crypto.tls; 019 020import static java.util.Objects.requireNonNull; 021 022import java.io.File; 023import java.io.FileOutputStream; 024import java.io.IOException; 025import java.lang.invoke.MethodHandles; 026import java.nio.charset.StandardCharsets; 027import java.security.GeneralSecurityException; 028import java.security.KeyPair; 029import java.security.Security; 030import java.security.cert.X509Certificate; 031import java.util.Arrays; 032import org.apache.commons.io.FileUtils; 033import org.apache.hadoop.conf.Configuration; 034import org.apache.yetus.audience.InterfaceAudience; 035import org.bouncycastle.asn1.x500.X500Name; 036import org.bouncycastle.asn1.x500.X500NameBuilder; 037import org.bouncycastle.asn1.x500.style.BCStyle; 038import org.bouncycastle.asn1.x509.GeneralName; 039import org.bouncycastle.asn1.x509.GeneralNames; 040import org.bouncycastle.jce.provider.BouncyCastleProvider; 041import org.bouncycastle.operator.OperatorCreationException; 042 043/** 044 * This class simplifies the creation of certificates and private keys for SSL/TLS connections. 045 * <p/> 046 * This file has been copied from the Apache ZooKeeper project. 047 * @see <a href= 048 * "https://github.com/apache/zookeeper/blob/c74658d398cdc1d207aa296cb6e20de00faec03e/zookeeper-server/src/test/java/org/apache/zookeeper/common/X509TestContext.java">Base 049 * revision</a> 050 */ 051@InterfaceAudience.Private 052public final class X509TestContext { 053 054 private static final String TRUST_STORE_PREFIX = "hbase_test_ca"; 055 private static final String KEY_STORE_PREFIX = "hbase_test_key"; 056 057 private final File tempDir; 058 private final Configuration conf; 059 060 private X509Certificate trustStoreCertificate; 061 private final char[] trustStorePassword; 062 private KeyPair trustStoreKeyPair; 063 private File trustStoreJksFile; 064 private File trustStorePemFile; 065 private File trustStorePkcs12File; 066 private File trustStoreBcfksFile; 067 068 private KeyPair keyStoreKeyPair; 069 private X509Certificate keyStoreCertificate; 070 private final char[] keyStorePassword; 071 private File keyStoreJksFile; 072 private File keyStorePemFile; 073 private File keyStorePkcs12File; 074 private File keyStoreBcfksFile; 075 076 /** 077 * Constructor is intentionally private, use the Builder class instead. 078 * @param conf the configuration 079 * @param tempDir the directory in which key store and trust store temp files will be 080 * written. 081 * @param trustStoreKeyPair the key pair for the trust store. 082 * @param trustStorePassword the password to protect a JKS trust store (ignored for PEM trust 083 * stores). 084 * @param keyStoreKeyPair the key pair for the key store. 085 * @param keyStorePassword the password to protect the key store private key. 086 */ 087 private X509TestContext(Configuration conf, File tempDir, KeyPair trustStoreKeyPair, 088 char[] trustStorePassword, KeyPair keyStoreKeyPair, char[] keyStorePassword) 089 throws IOException, GeneralSecurityException, OperatorCreationException { 090 if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { 091 throw new IllegalStateException("BC Security provider was not found"); 092 } 093 this.conf = conf; 094 this.tempDir = requireNonNull(tempDir); 095 if (!tempDir.isDirectory()) { 096 throw new IllegalArgumentException("Not a directory: " + tempDir); 097 } 098 099 this.trustStoreKeyPair = trustStoreKeyPair; 100 this.trustStorePassword = requireNonNull(trustStorePassword); 101 this.keyStoreKeyPair = requireNonNull(keyStoreKeyPair); 102 this.keyStorePassword = requireNonNull(keyStorePassword); 103 104 createCertificates(); 105 106 trustStorePkcs12File = null; 107 trustStorePemFile = null; 108 trustStoreJksFile = null; 109 keyStorePkcs12File = null; 110 keyStorePemFile = null; 111 keyStoreJksFile = null; 112 } 113 114 /** 115 * Used by {@link #cloneWithNewKeystoreCert(X509Certificate)}. Should set all fields except 116 * generated keystore path fields 117 */ 118 private X509TestContext(File tempDir, Configuration conf, X509Certificate trustStoreCertificate, 119 char[] trustStorePassword, KeyPair trustStoreKeyPair, File trustStoreJksFile, 120 File trustStorePemFile, File trustStorePkcs12File, KeyPair keyStoreKeyPair, 121 char[] keyStorePassword, X509Certificate keyStoreCertificate) { 122 this.tempDir = tempDir; 123 this.conf = conf; 124 this.trustStoreCertificate = trustStoreCertificate; 125 this.trustStorePassword = trustStorePassword; 126 this.trustStoreKeyPair = trustStoreKeyPair; 127 this.trustStoreJksFile = trustStoreJksFile; 128 this.trustStorePemFile = trustStorePemFile; 129 this.trustStorePkcs12File = trustStorePkcs12File; 130 this.keyStoreKeyPair = keyStoreKeyPair; 131 this.keyStoreCertificate = keyStoreCertificate; 132 this.keyStorePassword = keyStorePassword; 133 keyStorePkcs12File = null; 134 keyStorePemFile = null; 135 keyStoreJksFile = null; 136 } 137 138 /** 139 * Generates a new certificate using this context's CA and keystoreKeyPair. By default, the cert 140 * will have localhost in the subjectAltNames. This can be overridden by passing one or more 141 * string arguments after the cert name. The expectation for those arguments is that they are 142 * valid DNS names. 143 */ 144 public X509Certificate newCert(X500Name name, String... subjectAltNames) 145 throws GeneralSecurityException, IOException, OperatorCreationException { 146 if (subjectAltNames.length == 0) { 147 return X509TestHelpers.newCert(trustStoreCertificate, trustStoreKeyPair, name, 148 keyStoreKeyPair.getPublic()); 149 } 150 GeneralName[] names = new GeneralName[subjectAltNames.length]; 151 for (int i = 0; i < subjectAltNames.length; i++) { 152 names[i] = new GeneralName(GeneralName.dNSName, subjectAltNames[i]); 153 } 154 return X509TestHelpers.newCert(trustStoreCertificate, trustStoreKeyPair, name, 155 keyStoreKeyPair.getPublic(), new GeneralNames(names)); 156 } 157 158 public File getTempDir() { 159 return tempDir; 160 } 161 162 public char[] getTrustStorePassword() { 163 return trustStorePassword; 164 } 165 166 /** 167 * Returns the path to the trust store file in the given format (JKS or PEM). Note that the file 168 * is created lazily, the first time this method is called. The trust store file is temporary and 169 * will be deleted on exit. 170 * @param storeFileType the store file type (JKS or PEM). 171 * @return the path to the trust store file. 172 * @throws IOException if there is an error creating the trust store file. 173 */ 174 public File getTrustStoreFile(KeyStoreFileType storeFileType) throws IOException { 175 switch (storeFileType) { 176 case JKS: 177 return getTrustStoreJksFile(); 178 case PEM: 179 return getTrustStorePemFile(); 180 case PKCS12: 181 return getTrustStorePkcs12File(); 182 case BCFKS: 183 return getTrustStoreBcfksFile(); 184 default: 185 throw new IllegalArgumentException("Invalid trust store type: " + storeFileType 186 + ", must be one of: " + Arrays.toString(KeyStoreFileType.values())); 187 } 188 } 189 190 private File getTrustStoreJksFile() throws IOException { 191 if (trustStoreJksFile == null) { 192 trustStoreJksFile = File.createTempFile(TRUST_STORE_PREFIX, 193 KeyStoreFileType.JKS.getDefaultFileExtension(), tempDir); 194 trustStoreJksFile.deleteOnExit(); 195 generateTrustStoreJksFile(); 196 } 197 return trustStoreJksFile; 198 } 199 200 private void generateTrustStoreJksFile() throws IOException { 201 try (final FileOutputStream trustStoreOutputStream = new FileOutputStream(trustStoreJksFile)) { 202 byte[] bytes = 203 X509TestHelpers.certToJavaTrustStoreBytes(trustStoreCertificate, trustStorePassword); 204 trustStoreOutputStream.write(bytes); 205 trustStoreOutputStream.flush(); 206 } catch (GeneralSecurityException e) { 207 throw new IOException(e); 208 } 209 } 210 211 private File getTrustStorePemFile() throws IOException { 212 if (trustStorePemFile == null) { 213 trustStorePemFile = File.createTempFile(TRUST_STORE_PREFIX, 214 KeyStoreFileType.PEM.getDefaultFileExtension(), tempDir); 215 trustStorePemFile.deleteOnExit(); 216 generateTrustStorePemFile(); 217 } 218 return trustStorePemFile; 219 } 220 221 private void generateTrustStorePemFile() throws IOException { 222 FileUtils.writeStringToFile(trustStorePemFile, 223 X509TestHelpers.pemEncodeX509Certificate(trustStoreCertificate), StandardCharsets.US_ASCII, 224 false); 225 } 226 227 private File getTrustStorePkcs12File() throws IOException { 228 if (trustStorePkcs12File == null) { 229 trustStorePkcs12File = File.createTempFile(TRUST_STORE_PREFIX, 230 KeyStoreFileType.PKCS12.getDefaultFileExtension(), tempDir); 231 trustStorePkcs12File.deleteOnExit(); 232 generateTrustStorePkcs12File(); 233 } 234 return trustStorePkcs12File; 235 } 236 237 private void generateTrustStorePkcs12File() throws IOException { 238 try ( 239 final FileOutputStream trustStoreOutputStream = new FileOutputStream(trustStorePkcs12File)) { 240 byte[] bytes = 241 X509TestHelpers.certToPKCS12TrustStoreBytes(trustStoreCertificate, trustStorePassword); 242 trustStoreOutputStream.write(bytes); 243 trustStoreOutputStream.flush(); 244 } catch (GeneralSecurityException e) { 245 throw new IOException(e); 246 } 247 } 248 249 private File getTrustStoreBcfksFile() throws IOException { 250 if (trustStoreBcfksFile == null) { 251 trustStoreBcfksFile = File.createTempFile(TRUST_STORE_PREFIX, 252 KeyStoreFileType.BCFKS.getDefaultFileExtension(), tempDir); 253 trustStoreBcfksFile.deleteOnExit(); 254 generateTrustStoreBcfksFile(); 255 } 256 return trustStoreBcfksFile; 257 } 258 259 private void generateTrustStoreBcfksFile() throws IOException { 260 try ( 261 final FileOutputStream trustStoreOutputStream = new FileOutputStream(trustStoreBcfksFile)) { 262 byte[] bytes = 263 X509TestHelpers.certToBCFKSTrustStoreBytes(trustStoreCertificate, trustStorePassword); 264 trustStoreOutputStream.write(bytes); 265 trustStoreOutputStream.flush(); 266 } catch (GeneralSecurityException e) { 267 throw new IOException(e); 268 } 269 } 270 271 public X509Certificate getKeyStoreCertificate() { 272 return keyStoreCertificate; 273 } 274 275 public char[] getKeyStorePassword() { 276 return keyStorePassword; 277 } 278 279 public boolean isKeyStoreEncrypted() { 280 return keyStorePassword != null; 281 } 282 283 public Configuration getConf() { 284 return conf; 285 } 286 287 /** 288 * Returns the path to the key store file in the given format (JKS, PEM, ...). Note that the file 289 * is created lazily, the first time this method is called. The key store file is temporary and 290 * will be deleted on exit. 291 * @param storeFileType the store file type (JKS, PEM, ...). 292 * @return the path to the key store file. 293 * @throws IOException if there is an error creating the key store file. 294 */ 295 public File getKeyStoreFile(KeyStoreFileType storeFileType) throws IOException { 296 switch (storeFileType) { 297 case JKS: 298 return getKeyStoreJksFile(); 299 case PEM: 300 return getKeyStorePemFile(); 301 case PKCS12: 302 return getKeyStorePkcs12File(); 303 case BCFKS: 304 return getKeyStoreBcfksFile(); 305 default: 306 throw new IllegalArgumentException("Invalid key store type: " + storeFileType 307 + ", must be one of: " + Arrays.toString(KeyStoreFileType.values())); 308 } 309 } 310 311 private File getKeyStoreJksFile() throws IOException { 312 if (keyStoreJksFile == null) { 313 keyStoreJksFile = File.createTempFile(KEY_STORE_PREFIX, 314 KeyStoreFileType.JKS.getDefaultFileExtension(), tempDir); 315 keyStoreJksFile.deleteOnExit(); 316 generateKeyStoreJksFile(); 317 } 318 return keyStoreJksFile; 319 } 320 321 private void generateKeyStoreJksFile() throws IOException { 322 try (final FileOutputStream keyStoreOutputStream = new FileOutputStream(keyStoreJksFile)) { 323 byte[] bytes = X509TestHelpers.certAndPrivateKeyToJavaKeyStoreBytes(keyStoreCertificate, 324 keyStoreKeyPair.getPrivate(), keyStorePassword); 325 keyStoreOutputStream.write(bytes); 326 keyStoreOutputStream.flush(); 327 } catch (GeneralSecurityException e) { 328 throw new IOException(e); 329 } 330 } 331 332 private File getKeyStorePemFile() throws IOException { 333 if (keyStorePemFile == null) { 334 try { 335 keyStorePemFile = File.createTempFile(KEY_STORE_PREFIX, 336 KeyStoreFileType.PEM.getDefaultFileExtension(), tempDir); 337 keyStorePemFile.deleteOnExit(); 338 generateKeyStorePemFile(); 339 } catch (OperatorCreationException e) { 340 throw new IOException(e); 341 } 342 } 343 return keyStorePemFile; 344 } 345 346 private void generateKeyStorePemFile() throws IOException, OperatorCreationException { 347 FileUtils.writeStringToFile(keyStorePemFile, 348 X509TestHelpers.pemEncodeCertAndPrivateKey(keyStoreCertificate, keyStoreKeyPair.getPrivate(), 349 keyStorePassword), 350 StandardCharsets.US_ASCII, false); 351 } 352 353 private File getKeyStorePkcs12File() throws IOException { 354 if (keyStorePkcs12File == null) { 355 keyStorePkcs12File = File.createTempFile(KEY_STORE_PREFIX, 356 KeyStoreFileType.PKCS12.getDefaultFileExtension(), tempDir); 357 keyStorePkcs12File.deleteOnExit(); 358 generateKeyStorePkcs12File(); 359 } 360 return keyStorePkcs12File; 361 } 362 363 private void generateKeyStorePkcs12File() throws IOException { 364 try (final FileOutputStream keyStoreOutputStream = new FileOutputStream(keyStorePkcs12File)) { 365 byte[] bytes = X509TestHelpers.certAndPrivateKeyToPKCS12Bytes(keyStoreCertificate, 366 keyStoreKeyPair.getPrivate(), keyStorePassword); 367 keyStoreOutputStream.write(bytes); 368 keyStoreOutputStream.flush(); 369 } catch (GeneralSecurityException e) { 370 throw new IOException(e); 371 } 372 } 373 374 private File getKeyStoreBcfksFile() throws IOException { 375 if (keyStoreBcfksFile == null) { 376 keyStoreBcfksFile = File.createTempFile(KEY_STORE_PREFIX, 377 KeyStoreFileType.BCFKS.getDefaultFileExtension(), tempDir); 378 keyStoreBcfksFile.deleteOnExit(); 379 generateKeyStoreBcfksFile(); 380 } 381 return keyStoreBcfksFile; 382 } 383 384 private void generateKeyStoreBcfksFile() throws IOException { 385 try (final FileOutputStream keyStoreOutputStream = new FileOutputStream(keyStoreBcfksFile)) { 386 byte[] bytes = X509TestHelpers.certAndPrivateKeyToBCFKSBytes(keyStoreCertificate, 387 keyStoreKeyPair.getPrivate(), keyStorePassword); 388 keyStoreOutputStream.write(bytes); 389 keyStoreOutputStream.flush(); 390 } catch (GeneralSecurityException e) { 391 throw new IOException(e); 392 } 393 } 394 395 /** 396 * Sets the SSL system properties such that the given X509Util object can be used to create SSL 397 * Contexts that will use the trust store and key store files created by this test context. 398 * Example usage: 399 * 400 * <pre> 401 * X509TestContext testContext = ...; // create the test context 402 * X509Util x509Util = new QuorumX509Util(); 403 * testContext.setSystemProperties(x509Util, KeyStoreFileType.JKS, KeyStoreFileType.JKS); 404 * // The returned context will use the key store and trust store created by the test context. 405 * SSLContext ctx = x509Util.getDefaultSSLContext(); 406 * </pre> 407 * 408 * @param keyStoreFileType the store file type to use for the key store (JKS, PEM, ...). 409 * @param trustStoreFileType the store file type to use for the trust store (JKS, PEM, ...). 410 * @throws IOException if there is an error creating the key store file or trust store file. 411 */ 412 public void setConfigurations(KeyStoreFileType keyStoreFileType, 413 KeyStoreFileType trustStoreFileType) throws IOException { 414 setKeystoreConfigurations(keyStoreFileType, conf); 415 conf.set(X509Util.TLS_CONFIG_TRUSTSTORE_LOCATION, 416 this.getTrustStoreFile(trustStoreFileType).getAbsolutePath()); 417 conf.set(X509Util.TLS_CONFIG_TRUSTSTORE_PASSWORD, String.valueOf(this.getTrustStorePassword())); 418 conf.set(X509Util.TLS_CONFIG_TRUSTSTORE_TYPE, trustStoreFileType.getPropertyValue()); 419 } 420 421 /** 422 * Sets the KeyStore-related SSL system properties onto the given Configuration such that X509Util 423 * can be used to create SSL Contexts using that KeyStore. This can be used in special 424 * circumstances to inject a "bad" certificate where the keystore doesn't match the CA in the 425 * truststore. Or use it to create a connection without a truststore. 426 * @see #setConfigurations(KeyStoreFileType, KeyStoreFileType) which sets both keystore and 427 * truststore and is more applicable to general use. 428 */ 429 public void setKeystoreConfigurations(KeyStoreFileType keyStoreFileType, Configuration confToSet) 430 throws IOException { 431 432 confToSet.set(X509Util.TLS_CONFIG_KEYSTORE_LOCATION, 433 this.getKeyStoreFile(keyStoreFileType).getAbsolutePath()); 434 confToSet.set(X509Util.TLS_CONFIG_KEYSTORE_PASSWORD, 435 String.valueOf(this.getKeyStorePassword())); 436 confToSet.set(X509Util.TLS_CONFIG_KEYSTORE_TYPE, keyStoreFileType.getPropertyValue()); 437 } 438 439 public void clearConfigurations() { 440 conf.unset(X509Util.TLS_CONFIG_KEYSTORE_LOCATION); 441 conf.unset(X509Util.TLS_CONFIG_KEYSTORE_PASSWORD); 442 conf.unset(X509Util.TLS_CONFIG_KEYSTORE_TYPE); 443 conf.unset(X509Util.TLS_CONFIG_TRUSTSTORE_LOCATION); 444 conf.unset(X509Util.TLS_CONFIG_TRUSTSTORE_PASSWORD); 445 conf.unset(X509Util.TLS_CONFIG_TRUSTSTORE_TYPE); 446 } 447 448 /** 449 * Creates a clone of the current context, but injecting the passed certificate as the KeyStore 450 * cert. The new context's keystore path fields are nulled, so the next call to 451 * {@link #setConfigurations(KeyStoreFileType, KeyStoreFileType)}, 452 * {@link #setKeystoreConfigurations(KeyStoreFileType, Configuration)} , or 453 * {@link #getKeyStoreFile(KeyStoreFileType)} will create a new keystore with this certificate in 454 * place. 455 * @param cert the cert to replace 456 */ 457 public X509TestContext cloneWithNewKeystoreCert(X509Certificate cert) { 458 return new X509TestContext(tempDir, conf, trustStoreCertificate, trustStorePassword, 459 trustStoreKeyPair, trustStoreJksFile, trustStorePemFile, trustStorePkcs12File, 460 keyStoreKeyPair, keyStorePassword, cert); 461 } 462 463 public void regenerateStores(X509KeyType keyStoreKeyType, X509KeyType trustStoreKeyType, 464 KeyStoreFileType keyStoreFileType, KeyStoreFileType trustStoreFileType) 465 throws GeneralSecurityException, IOException, OperatorCreationException { 466 467 trustStoreKeyPair = X509TestHelpers.generateKeyPair(trustStoreKeyType); 468 keyStoreKeyPair = X509TestHelpers.generateKeyPair(keyStoreKeyType); 469 createCertificates(); 470 471 switch (keyStoreFileType) { 472 case JKS: 473 generateKeyStoreJksFile(); 474 break; 475 case PEM: 476 generateKeyStorePemFile(); 477 break; 478 case BCFKS: 479 generateKeyStoreBcfksFile(); 480 break; 481 case PKCS12: 482 generateKeyStorePkcs12File(); 483 break; 484 } 485 486 switch (trustStoreFileType) { 487 case JKS: 488 generateTrustStoreJksFile(); 489 break; 490 case PEM: 491 generateTrustStorePemFile(); 492 break; 493 case PKCS12: 494 generateTrustStorePkcs12File(); 495 break; 496 case BCFKS: 497 generateTrustStoreBcfksFile(); 498 break; 499 } 500 } 501 502 private void createCertificates() 503 throws GeneralSecurityException, IOException, OperatorCreationException { 504 X500NameBuilder caNameBuilder = new X500NameBuilder(BCStyle.INSTANCE); 505 caNameBuilder.addRDN(BCStyle.CN, 506 MethodHandles.lookup().lookupClass().getCanonicalName() + " Root CA"); 507 trustStoreCertificate = 508 X509TestHelpers.newSelfSignedCACert(caNameBuilder.build(), trustStoreKeyPair); 509 510 X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE); 511 nameBuilder.addRDN(BCStyle.CN, 512 MethodHandles.lookup().lookupClass().getCanonicalName() + " Zookeeper Test"); 513 keyStoreCertificate = newCert(nameBuilder.build()); 514 } 515 516 /** 517 * Builder class, used for creating new instances of X509TestContext. 518 */ 519 public static class Builder { 520 521 private final Configuration conf; 522 private File tempDir; 523 private X509KeyType trustStoreKeyType; 524 private char[] trustStorePassword; 525 private X509KeyType keyStoreKeyType; 526 private char[] keyStorePassword; 527 528 /** 529 * Creates an empty builder with the given Configuration. 530 */ 531 public Builder(Configuration conf) { 532 this.conf = conf; 533 trustStoreKeyType = X509KeyType.EC; 534 keyStoreKeyType = X509KeyType.EC; 535 } 536 537 /** 538 * Builds a new X509TestContext from this builder. 539 * @return a new X509TestContext 540 */ 541 public X509TestContext build() 542 throws IOException, GeneralSecurityException, OperatorCreationException { 543 KeyPair trustStoreKeyPair = X509TestHelpers.generateKeyPair(trustStoreKeyType); 544 KeyPair keyStoreKeyPair = X509TestHelpers.generateKeyPair(keyStoreKeyType); 545 return new X509TestContext(conf, tempDir, trustStoreKeyPair, trustStorePassword, 546 keyStoreKeyPair, keyStorePassword); 547 } 548 549 /** 550 * Sets the temporary directory. Certificate and private key files will be created in this 551 * directory. 552 * @param tempDir the temp directory. 553 * @return this Builder. 554 */ 555 public Builder setTempDir(File tempDir) { 556 this.tempDir = tempDir; 557 return this; 558 } 559 560 /** 561 * Sets the trust store key type. The CA key generated for the test context will be of this 562 * type. 563 * @param keyType the key type. 564 * @return this Builder. 565 */ 566 public Builder setTrustStoreKeyType(X509KeyType keyType) { 567 trustStoreKeyType = keyType; 568 return this; 569 } 570 571 /** 572 * Sets the trust store password. Ignored for PEM trust stores, JKS trust stores will be 573 * encrypted with this password. 574 * @param password the password. 575 * @return this Builder. 576 */ 577 public Builder setTrustStorePassword(char[] password) { 578 trustStorePassword = password; 579 return this; 580 } 581 582 /** 583 * Sets the key store key type. The private key generated for the test context will be of this 584 * type. 585 * @param keyType the key type. 586 * @return this Builder. 587 */ 588 public Builder setKeyStoreKeyType(X509KeyType keyType) { 589 keyStoreKeyType = keyType; 590 return this; 591 } 592 593 /** 594 * Sets the key store password. The private key (PEM, JKS) and certificate (JKS only) will be 595 * encrypted with this password. 596 * @param password the password. 597 * @return this Builder. 598 */ 599 public Builder setKeyStorePassword(char[] password) { 600 keyStorePassword = password; 601 return this; 602 } 603 } 604 605 /** 606 * Returns a new default-constructed Builder. 607 * @return a new Builder. 608 */ 609 public static Builder newBuilder(Configuration conf) { 610 return new Builder(conf); 611 } 612}