-
Notifications
You must be signed in to change notification settings - Fork 46
Expand file tree
/
Copy pathTlsContextOptions.java
More file actions
609 lines (554 loc) · 24 KB
/
Copy pathTlsContextOptions.java
File metadata and controls
609 lines (554 loc) · 24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
package software.amazon.awssdk.crt.io;
import java.util.ArrayList;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.function.Consumer;
import software.amazon.awssdk.crt.CrtResource;
import software.amazon.awssdk.crt.CrtRuntimeException;
import software.amazon.awssdk.crt.utils.PemUtils;
import software.amazon.awssdk.crt.utils.StringUtils;
/**
* This class wraps the aws_tls_connection_options from aws-c-io to provide
* access to TLS configuration contexts in the AWS Common Runtime.
*/
public final class TlsContextOptions extends CrtResource {
public enum TlsVersions {
/**
* SSL v3. This should almost never be used.
*/
SSLv3(0),
TLSv1(1),
/**
* TLS 1.1
*/
TLSv1_1(2),
/**
* TLS 1.2
*/
TLSv1_2(3),
/**
* TLS 1.3
*/
TLSv1_3(4),
/**
* Use whatever the system default is. This is usually the best option, as it will be automatically updated
* as the underlying OS or platform changes.
*/
TLS_VER_SYS_DEFAULTS(128);
private int version;
TlsVersions(int val) {
version = val;
}
int getValue() { return version; }
}
/**
* Sets the minimum acceptable TLS version that the {@link TlsContext} will
* allow. Not compatible with setCipherPreference() API.
*
* Select from TlsVersions, a good default is TlsVersions.TLS_VER_SYS_DEFAULTS
* as this will update if the OS TLS is updated
*/
public TlsVersions minTlsVersion = TlsVersions.TLS_VER_SYS_DEFAULTS;
/**
* Sets the TLS Cipher Preferences that can be negotiated and used during the
* TLS Connection. Not compatible with setMinimumTlsVersion() API.
*
*/
public TlsCipherPreference tlsCipherPreference = TlsCipherPreference.TLS_CIPHER_SYSTEM_DEFAULT;
/**
* Sets the ALPN protocol list that will be provided when a TLS connection
* starts e.g. "x-amzn-mqtt-ca"
*/
public List<String> alpnList = new ArrayList<>();
/**
* Set whether or not the peer should be verified. Default is true for clients,
* and false for servers. If you are in a development or debugging environment,
* you can disable this to avoid or diagnose trust store issues. This should
* always be true on clients in the wild. If you set this to true on a server,
* it will validate every client connection.
*/
public boolean verifyPeer = false;
/**
* Set to true to disable certificate revocation checking during TLS negotiation.
*
* On Windows (SChannel), this prevents the TLS handshake from making outbound network calls
* to CRL/OCSP revocation endpoints, which can block for minutes when the endpoints are unreachable
* (e.g., in private subnets without internet access).
*
* On Linux (s2n), this disables validation of OCSP stapled responses provided by the server.
*
* On Apple platforms, this is a no-op as revocation checking is not enabled by default.
*
* Default is false (revocation checking enabled where available).
*/
public boolean noCertificateRevocation = false;
private String certificate;
private String privateKey;
private String certificatePath;
private String privateKeyPath;
private String caRoot;
private String caFile;
private String caDir;
private String pkcs12Path;
private String pkcs12Password;
private TlsContextPkcs11Options pkcs11Options;
private TlsContextCustomKeyOperationOptions customKeyOperations;
private String windowsCertStorePath;
/**
* Creates a new set of options that can be used to create a {@link TlsContext}
*/
private TlsContextOptions() {
}
@Override
public long getNativeHandle() {
if (super.getNativeHandle() == 0) {
if (tlsCipherPreference != TlsCipherPreference.TLS_CIPHER_SYSTEM_DEFAULT
&& minTlsVersion != TlsVersions.TLS_VER_SYS_DEFAULTS) {
throw new IllegalStateException("tlsCipherPreference and minTlsVersion are mutually exclusive");
}
acquireNativeHandle(tlsContextOptionsNew(
minTlsVersion.getValue(),
tlsCipherPreference.getValue(),
alpnList.size() > 0 ? StringUtils.join(";", alpnList) : null,
certificate,
privateKey,
certificatePath,
privateKeyPath,
caRoot,
caFile,
caDir,
verifyPeer,
noCertificateRevocation,
pkcs12Path,
pkcs12Password,
pkcs11Options,
customKeyOperations,
windowsCertStorePath
));
}
return super.getNativeHandle();
}
/**
* Determines whether a resource releases its dependencies at the same time the native handle is released or if it waits.
* Resources that wait are responsible for calling releaseReferences() manually.
*/
@Override
protected boolean canReleaseReferencesImmediately() { return true; }
/**
* Frees the native resources associated with this instance
*/
@Override
protected void releaseNativeHandle() {
// It is perfectly acceptable for this to have never created a native resource
if (!isNull()) {
tlsContextOptionsDestroy(getNativeHandle());
}
}
/**
* Sets the TLS cipher preferences to use in contexts using this configuration
* @param cipherPref cipher preferences to use
*/
public void setCipherPreference(TlsCipherPreference cipherPref) {
if(!isCipherPreferenceSupported(cipherPref)) {
throw new IllegalArgumentException("TlsCipherPreference is not supported on this platform: " + cipherPref.name());
}
if (this.minTlsVersion != TlsVersions.TLS_VER_SYS_DEFAULTS && cipherPref != TlsCipherPreference.TLS_CIPHER_SYSTEM_DEFAULT) {
throw new IllegalArgumentException("Currently only setMinimumTlsVersion() or setCipherPreference() may be used, not both.");
}
this.tlsCipherPreference = cipherPref;
}
/**
* Sets the path to the certificate that identifies this mutual TLS (mTLS) host. Must be in PEM format.
* @param certificatePath Path to PEM format certificate
* @param privateKeyPath Path to PEM format private key
*/
public void initMtlsFromPath(String certificatePath, String privateKeyPath) {
this.certificatePath = certificatePath;
this.privateKeyPath = privateKeyPath;
}
/**
* Sets the certificate/key pair that identifies this mutual TLS (mTLS) host. Must be in
* PEM format.
*
* @param certificate PEM armored certificate
* @param privateKey PEM armored private key
* @throws IllegalArgumentException If the certificate or privateKey are not in PEM format or if they contain chains
*/
public void initMtls(String certificate, String privateKey) throws IllegalArgumentException {
this.certificate = PemUtils.cleanUpPem(certificate);
PemUtils.sanityCheck(certificate, 1, "CERTIFICATE");
this.privateKey = PemUtils.cleanUpPem(privateKey);
PemUtils.sanityCheck(privateKey, 1, "PRIVATE KEY");
}
/**
* Apple platforms only - Initializes mutual TLS (mTLS) with PKCS12 file and password
* @param pkcs12Path Path to PKCS12 file
* @param pkcs12Password PKCS12 password
*/
public void initMtlsPkcs12(String pkcs12Path, String pkcs12Password) {
if (this.certificate != null || this.privateKey != null || this.certificatePath != null
|| this.privateKeyPath != null) {
throw new IllegalArgumentException(
"PKCS#12 and mTLS via certificate/private key pair are mutually exclusive");
}
this.pkcs12Path = pkcs12Path;
this.pkcs12Password = pkcs12Password;
}
/**
* Returns whether or not ALPN is supported on the current platform
* @return true if ALPN is supported, false otherwise
*/
public static boolean isAlpnSupported() {
return tlsContextOptionsIsAlpnAvailable();
}
/**
* Returns whether or not the current platform can be configured to a specific TlsCipherPreference.
* @param cipherPref The TlsCipherPreference to check
* @return True if the current platform does support this TlsCipherPreference, false otherwise
*/
public static boolean isCipherPreferenceSupported(TlsCipherPreference cipherPref) {
return tlsContextOptionsIsCipherPreferenceSupported(cipherPref.getValue());
}
/**
* Helper function to provide a TlsContext-local trust store
* @param caPath Path to the local trust store. Can be null.
* @param caFile Path to the root certificate. Must be in PEM format.
*/
public void overrideDefaultTrustStoreFromPath(String caPath, String caFile) {
if (this.caRoot != null) {
throw new IllegalArgumentException("Certificate authority is already specified via PEM buffer");
}
this.caDir = caPath;
this.caFile = caFile;
}
/**
* Helper function to provide a TlsContext-local trust store
*
* @param caRoot Buffer containing the root certificate chain. Must be in PEM format.
* @throws IllegalArgumentException if the CA Root PEM file is malformed
*/
public void overrideDefaultTrustStore(String caRoot) throws IllegalArgumentException {
if (this.caFile != null || this.caDir != null) {
throw new IllegalArgumentException("Certificate authority is already specified via path(s)");
}
this.caRoot = PemUtils.cleanUpPem(caRoot);
// 1024 certs in the chain is the default supported by s2n:
PemUtils.sanityCheck(this.caRoot, 1024, "CERTIFICATE");
}
/**
* Helper which creates a default set of TLS options for the current platform
* @return A default configured set of options for a TLS client connection
*/
public static TlsContextOptions createDefaultClient() {
TlsContextOptions options = new TlsContextOptions();
options.verifyPeer = true;
return options;
}
/**
* Helper which creates a default set of TLS options for the current platform
*
* @return A default configured set of options for a TLS server connection
*/
public static TlsContextOptions createDefaultServer() {
TlsContextOptions options = new TlsContextOptions();
options.verifyPeer = false;
return options;
}
/**
* Helper which creates mutual TLS (mTLS) options using a certificate and private key
* @param certificatePath Path to a PEM format certificate
* @param privateKeyPath Path to a PEM format private key
* @return A set of options for setting up an mTLS connection
*/
public static TlsContextOptions createWithMtlsFromPath(String certificatePath, String privateKeyPath) {
TlsContextOptions options = new TlsContextOptions();
options.initMtlsFromPath(certificatePath, privateKeyPath);
options.verifyPeer = true;
return options;
}
/**
* Helper which creates mutual TLS (mTLS) options using a certificate and private key
*
* @param certificate String containing a PEM format certificate
* @param privateKey String containing a PEM format private key
* @return A set of options for setting up an mTLS connection
* @throws IllegalArgumentException If either PEM fails to parse
*/
public static TlsContextOptions createWithMtls(String certificate, String privateKey)
throws IllegalArgumentException {
TlsContextOptions options = new TlsContextOptions();
options.initMtls(certificate, privateKey);
options.verifyPeer = true;
return options;
}
/**
* Apple platforms only - Helper which creates mutual TLS (mTLS) options using PKCS12
* @param pkcs12Path The path to a PKCS12 file @see #setPkcs12Path(String)
* @param pkcs12Password The PKCS12 password @see #setPkcs12Password(String)
* @return A set of options for creating a PKCS12 mTLS connection
*/
public static TlsContextOptions createWithMtlsPkcs12(String pkcs12Path, String pkcs12Password) {
TlsContextOptions options = new TlsContextOptions();
options.initMtlsPkcs12(pkcs12Path, pkcs12Password);
options.verifyPeer = true;
return options;
}
/**
* Unix platforms only - Helper which creates mutual TLS (mTLS) options using a PKCS#11 library for private key operations.
* @param pkcs11Options PKCS#11 options
* @return A set of options for creating a PKCS#11 mTLS connection
*/
public static TlsContextOptions createWithMtlsPkcs11(TlsContextPkcs11Options pkcs11Options) {
TlsContextOptions options = new TlsContextOptions();
options.withMtlsPkcs11(pkcs11Options);
options.verifyPeer = true;
return options;
}
/**
* Unix platforms only - Helper which creates mutual TLS (mTLS) options using the applied custom key operations. This
* allows you to perform custom private key operations such as signing and decrypting. This is necessary if you
* require an external library to handle private key operations.
*
* @param custom The options for the custom private key operations
* @return A set of options for creating a custom key operation mTLS connection
*/
public static TlsContextOptions createWithMtlsCustomKeyOperations(TlsContextCustomKeyOperationOptions custom) {
TlsContextOptions options = new TlsContextOptions();
options.withMtlsCustomKeyOperations(custom);
options.verifyPeer = true;
return options;
}
/**
* Windows platforms only - Helper which creates mutual TLS (mTLS) options using a
* certificate in a Windows certificate store.
*
* @param certificatePath Path to certificate in a Windows certificate store.
* The path must use backslashes and end with the
* certificate's thumbprint. Example:
* {@code CurrentUser\MY\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6}
* @return A set of options for setting up an mTLS connection
*/
public static TlsContextOptions createWithMtlsWindowsCertStorePath(String certificatePath) {
TlsContextOptions options = new TlsContextOptions();
options.withMtlsWindowsCertStorePath(certificatePath);
options.verifyPeer = true;
return options;
}
/**
* Helper which creates mutual TLS (mTLS) options using a certificate and private key
* stored in a Java keystore.
* Will throw an exception if there is no certificate and key at the given certificate alias, or there is some other
* error accessing or using the passed-in Java keystore.
*
* Note: function assumes the passed keystore has already been loaded from a file by calling "keystore.load()" or similar.
*
* @param keyStore The Java keystore to use. Assumed to be loaded with the desired certificate and key
* @param certificateAlias The alias of the certificate and key to use.
* @param certificatePassword The password of the certificate and key to use.
* @throws CrtRuntimeException if the certificate alias does not exist or the certificate/key cannot be found in the certificate alias
* @return A set of options for setting up an mTLS connection
*/
public static TlsContextOptions createWithMtlsJavaKeystore(
java.security.KeyStore keyStore, String certificateAlias, String certificatePassword) {
TlsContextOptions options = new TlsContextOptions();
String certificate;
try {
java.security.cert.Certificate certificateData = keyStore.getCertificate(certificateAlias);
if (certificateData == null) {
throw new CrtRuntimeException("Certificate at given certificate alias does not exist or does not contain a certificate");
}
String certificateString = new String(StringUtils.base64Encode(certificateData.getEncoded()));
certificate = "-----BEGIN CERTIFICATE-----\n" + certificateString + "-----END CERTIFICATE-----\n";
} catch (java.security.KeyStoreException | java.security.cert.CertificateEncodingException ex) {
throw new RuntimeException("Failed to get certificate from Java keystore", ex);
}
String privateKey;
try {
java.security.Key keyData = keyStore.getKey(certificateAlias, certificatePassword.toCharArray());
if (keyData == null) {
throw new CrtRuntimeException("Private key at given certificate alias does not exist or does not identify a key-related entity");
}
String keyString = new String(StringUtils.base64Encode(keyData.getEncoded()));
privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" + keyString + "-----END RSA PRIVATE KEY-----\n";
} catch (java.security.KeyStoreException | java.security.NoSuchAlgorithmException | java.security.UnrecoverableKeyException ex) {
throw new RuntimeException("Failed to get private key from Java keystore", ex);
}
options.initMtls(certificate, privateKey);
options.verifyPeer = true;
return options;
}
/*******************************************************************************
* .with() methods
******************************************************************************/
/**
* Sets the ciphers that the TlsContext will be able to use
* @param cipherPref The preference set of ciphers to use
* @return this
*/
public TlsContextOptions withCipherPreference(TlsCipherPreference cipherPref) {
setCipherPreference(cipherPref);
return this;
}
/**
* Sets the minimum TLS version that the TlsContext will allow. Defaults to
* OS defaults.
* @param version Minimum acceptable TLS version
* @return this
*/
public TlsContextOptions withMinimumTlsVersion(TlsVersions version) {
minTlsVersion = version;
return this;
}
/**
* Sets the ALPN protocols list for any connections using this TlsContext
* @param alpnList Semi-colon delimited list of supported ALPN protocols
* @return this
*/
public TlsContextOptions withAlpnList(String alpnList) {
String[] parts = alpnList.split(";");
for (String part : parts) {
this.alpnList.add(part);
}
return this;
}
/**
* Enables mutual TLS (mTLS) on this TlsContext
* @param certificate mTLS certificate, in PEM format
* @param privateKey mTLS private key, in PEM format
* @return this
*/
public TlsContextOptions withMtls(String certificate, String privateKey) {
this.initMtls(certificate, privateKey);
return this;
}
/**
* Enables mutual TLS (mTLS) on this TlsContext
* @param certificatePath path to mTLS certificate, in PEM format
* @param privateKeyPath path to mTLS private key, in PEM format
* @return this
*/
public TlsContextOptions withMtlsFromPath(String certificatePath, String privateKeyPath) {
this.initMtlsFromPath(certificatePath, privateKeyPath);
return this;
}
/**
* Specifies the certificate authority to use. By default, the OS CA repository will be used.
* @param caRoot Certificate Authority, in PEM format
* @return this
*/
public TlsContextOptions withCertificateAuthority(String caRoot) {
this.overrideDefaultTrustStore(caRoot);
return this;
}
/**
* Specifies the certificate authority to use.
* @param caDirPath Path to certificate directory, e.g. /etc/ssl/certs
* @param caFilePath Path to ceritificate authority, in PEM format
* @return this
*/
public TlsContextOptions withCertificateAuthorityFromPath(String caDirPath, String caFilePath) {
this.overrideDefaultTrustStoreFromPath(caDirPath, caFilePath);
return this;
}
/**
* Apple platforms only, specifies mutual TLS (mTLS) using PKCS#12
* @param pkcs12Path Path to PKCS#12 certificate, in PEM format
* @param pkcs12Password PKCS#12 password
* @return this
*/
public TlsContextOptions withMtlsPkcs12(String pkcs12Path, String pkcs12Password) {
this.initMtlsPkcs12(pkcs12Path, pkcs12Password);
return this;
}
/**
* Unix platforms only, specifies mutual TLS (mTLS) using a PKCS#11 library for private key operations.
* @param pkcs11Options PKCS#11 options
* @return this
*/
public TlsContextOptions withMtlsPkcs11(TlsContextPkcs11Options pkcs11Options) {
swapReferenceTo(this.pkcs11Options, pkcs11Options);
this.pkcs11Options = pkcs11Options;
return this;
}
/**
* Unix platforms only, specifies TLS options for custom private key operations. This
* allows you to perform custom private key operations such as signing and decrypting.
*
* @param customKeyOperations The custom private key operations
* @return this
*/
public TlsContextOptions withMtlsCustomKeyOperations(TlsContextCustomKeyOperationOptions customKeyOperations) {
this.customKeyOperations = customKeyOperations;
return this;
}
/**
* Windows platforms only, specifies mutual TLS (mTLS) using a certificate in a Windows
* certificate store.
*
* @param certificatePath Path to certificate in a Windows certificate store.
* The path must use backslashes and end with the
* certificate's thumbprint. Example:
* {@code CurrentUser\MY\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6}
* @return this
*/
public TlsContextOptions withMtlsWindowsCertStorePath(String certificatePath) {
this.windowsCertStorePath = certificatePath;
return this;
}
/**
* Sets whether or not TLS will validate the certificate from the peer. On clients,
* this is enabled by default. On servers, this is disabled by default.
* @param verify true to verify peers, false to ignore certs
* @return this
*/
public TlsContextOptions withVerifyPeer(boolean verify) {
this.verifyPeer = verify;
return this;
}
/**
* Enables TLS peer verification of certificates
* @see TlsContextOptions#withVerifyPeer(boolean)
* @return this
*/
public TlsContextOptions withVerifyPeer() {
return this.withVerifyPeer(true);
}
/**
* Disables certificate revocation checking during TLS negotiation.
*
* @return this
*/
public TlsContextOptions withNoCertificateRevocation() {
this.noCertificateRevocation = true;
return this;
}
/*******************************************************************************
* native methods
******************************************************************************/
private static native long tlsContextOptionsNew(
int minTlsVersion,
int cipherPref,
String alpn,
String certificate,
String privateKey,
String certificatePath,
String privateKeyPath,
String caRoot,
String caFile,
String caDir,
boolean verifyPeer,
boolean noCertificateRevocation,
String pkcs12Path,
String pkcs12Password,
TlsContextPkcs11Options pkcs11Options,
TlsContextCustomKeyOperationOptions customKeyOperation,
String windowsCertStorePath
);
private static native void tlsContextOptionsDestroy(long elg);
private static native boolean tlsContextOptionsIsAlpnAvailable();
private static native boolean tlsContextOptionsIsCipherPreferenceSupported(int cipherPref);
};