Skip to content

Commit fb00463

Browse files
authored
fix a flaky test in advanced TLS (#8474)
* fix a flaky test in advanced tls
1 parent 1f1396f commit fb00463

File tree

3 files changed

+47
-20
lines changed

3 files changed

+47
-20
lines changed

core/src/main/java/io/grpc/util/AdvancedTlsX509KeyManager.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@
2323
import java.io.FileInputStream;
2424
import java.io.IOException;
2525
import java.net.Socket;
26-
import java.security.NoSuchAlgorithmException;
26+
import java.security.GeneralSecurityException;
2727
import java.security.Principal;
2828
import java.security.PrivateKey;
2929
import java.security.cert.CertificateException;
3030
import java.security.cert.X509Certificate;
31-
import java.security.spec.InvalidKeySpecException;
3231
import java.util.Arrays;
3332
import java.util.concurrent.ScheduledExecutorService;
3433
import java.util.concurrent.ScheduledFuture;
@@ -107,8 +106,7 @@ public String chooseEngineServerAlias(String keyType, Principal[] issuers,
107106
* @param key the private key that is going to be used
108107
* @param certs the certificate chain that is going to be used
109108
*/
110-
public void updateIdentityCredentials(PrivateKey key, X509Certificate[] certs)
111-
throws CertificateException {
109+
public void updateIdentityCredentials(PrivateKey key, X509Certificate[] certs) {
112110
// TODO(ZhenLian): explore possibilities to do a crypto check here.
113111
this.keyInfo = new KeyInfo(checkNotNull(key, "key"), checkNotNull(certs, "certs"));
114112
}
@@ -126,10 +124,16 @@ public void updateIdentityCredentials(PrivateKey key, X509Certificate[] certs)
126124
* @return an object that caller should close when the file refreshes are not needed
127125
*/
128126
public Closeable updateIdentityCredentialsFromFile(File keyFile, File certFile,
129-
long period, TimeUnit unit, ScheduledExecutorService executor) {
127+
long period, TimeUnit unit, ScheduledExecutorService executor) throws IOException,
128+
GeneralSecurityException {
129+
UpdateResult newResult = readAndUpdate(keyFile, certFile, 0, 0);
130+
if (!newResult.success) {
131+
throw new GeneralSecurityException(
132+
"Files were unmodified before their initial update. Probably a bug.");
133+
}
130134
final ScheduledFuture<?> future =
131135
executor.scheduleWithFixedDelay(
132-
new LoadFilePathExecution(keyFile, certFile), 0, period, unit);
136+
new LoadFilePathExecution(keyFile, certFile), period, period, unit);
133137
return new Closeable() {
134138
@Override public void close() {
135139
future.cancel(false);
@@ -170,8 +174,7 @@ public void run() {
170174
this.currentKeyTime = newResult.keyTime;
171175
this.currentCertTime = newResult.certTime;
172176
}
173-
} catch (CertificateException | IOException | NoSuchAlgorithmException
174-
| InvalidKeySpecException e) {
177+
} catch (IOException | GeneralSecurityException e) {
175178
log.log(Level.SEVERE, "Failed refreshing private key and certificate chain from files. "
176179
+ "Using previous ones", e);
177180
}
@@ -201,7 +204,7 @@ public UpdateResult(boolean success, long keyTime, long certTime) {
201204
* @return the result of this update execution
202205
*/
203206
private UpdateResult readAndUpdate(File keyFile, File certFile, long oldKeyTime, long oldCertTime)
204-
throws IOException, CertificateException, NoSuchAlgorithmException, InvalidKeySpecException {
207+
throws IOException, GeneralSecurityException {
205208
long newKeyTime = keyFile.lastModified();
206209
long newCertTime = certFile.lastModified();
207210
// We only update when both the key and the certs are updated.

core/src/main/java/io/grpc/util/AdvancedTlsX509TrustManager.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.io.FileInputStream;
2222
import java.io.IOException;
2323
import java.net.Socket;
24+
import java.security.GeneralSecurityException;
2425
import java.security.KeyStore;
2526
import java.security.KeyStoreException;
2627
import java.security.NoSuchAlgorithmException;
@@ -124,8 +125,8 @@ public void useSystemDefaultTrustCerts() throws CertificateException, KeyStoreEx
124125
*
125126
* @param trustCerts the trust certificates that are going to be used
126127
*/
127-
public void updateTrustCredentials(X509Certificate[] trustCerts) throws CertificateException,
128-
KeyStoreException, NoSuchAlgorithmException, IOException {
128+
public void updateTrustCredentials(X509Certificate[] trustCerts) throws IOException,
129+
GeneralSecurityException {
129130
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
130131
keyStore.load(null, null);
131132
int i = 1;
@@ -219,10 +220,15 @@ private void checkTrusted(X509Certificate[] chain, String authType, SSLEngine ss
219220
* @return an object that caller should close when the file refreshes are not needed
220221
*/
221222
public Closeable updateTrustCredentialsFromFile(File trustCertFile, long period, TimeUnit unit,
222-
ScheduledExecutorService executor) {
223+
ScheduledExecutorService executor) throws IOException, GeneralSecurityException {
224+
long updatedTime = readAndUpdate(trustCertFile, 0);
225+
if (updatedTime == 0) {
226+
throw new GeneralSecurityException(
227+
"Files were unmodified before their initial update. Probably a bug.");
228+
}
223229
final ScheduledFuture<?> future =
224230
executor.scheduleWithFixedDelay(
225-
new LoadFilePathExecution(trustCertFile), 0, period, unit);
231+
new LoadFilePathExecution(trustCertFile), period, period, unit);
226232
return new Closeable() {
227233
@Override public void close() {
228234
future.cancel(false);
@@ -243,8 +249,7 @@ public LoadFilePathExecution(File file) {
243249
public void run() {
244250
try {
245251
this.currentTime = readAndUpdate(this.file, this.currentTime);
246-
} catch (CertificateException | IOException | KeyStoreException
247-
| NoSuchAlgorithmException e) {
252+
} catch (IOException | GeneralSecurityException e) {
248253
log.log(Level.SEVERE, "Failed refreshing trust CAs from file. Using previous CAs", e);
249254
}
250255
}
@@ -259,7 +264,7 @@ public void run() {
259264
* @return oldTime if failed or the modified time is not changed, otherwise the new modified time
260265
*/
261266
private long readAndUpdate(File trustCertFile, long oldTime)
262-
throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException {
267+
throws IOException, GeneralSecurityException {
263268
long newTime = trustCertFile.lastModified();
264269
if (newTime == oldTime) {
265270
return oldTime;

netty/src/test/java/io/grpc/netty/AdvancedTlsTest.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.io.File;
4646
import java.io.IOException;
4747
import java.net.Socket;
48+
import java.security.GeneralSecurityException;
4849
import java.security.NoSuchAlgorithmException;
4950
import java.security.PrivateKey;
5051
import java.security.cert.CertificateException;
@@ -169,7 +170,6 @@ public void advancedTlsKeyManagerTrustManagerMutualTlsTest() throws Exception {
169170
.clientAuth(ClientAuth.REQUIRE).build();
170171
server = Grpc.newServerBuilderForPort(0, serverCredentials).addService(
171172
new SimpleServiceImpl()).build().start();
172-
TimeUnit.SECONDS.sleep(5);
173173
// Create a client with the key manager and trust manager.
174174
AdvancedTlsX509KeyManager clientKeyManager = new AdvancedTlsX509KeyManager();
175175
clientKeyManager.updateIdentityCredentials(clientKey0, clientCert0);
@@ -232,7 +232,6 @@ public void verifyPeerCertificate(X509Certificate[] peerCertChain, String authTy
232232
.clientAuth(ClientAuth.REQUIRE).build();
233233
server = Grpc.newServerBuilderForPort(0, serverCredentials).addService(
234234
new SimpleServiceImpl()).build().start();
235-
TimeUnit.SECONDS.sleep(5);
236235

237236
AdvancedTlsX509KeyManager clientKeyManager = new AdvancedTlsX509KeyManager();
238237
clientKeyManager.updateIdentityCredentials(clientKey0, clientCert0);
@@ -307,7 +306,6 @@ public void verifyPeerCertificate(X509Certificate[] peerCertChain, String authTy
307306
.clientAuth(ClientAuth.REQUIRE).build();
308307
server = Grpc.newServerBuilderForPort(0, serverCredentials).addService(
309308
new SimpleServiceImpl()).build().start();
310-
TimeUnit.SECONDS.sleep(5);
311309

312310
AdvancedTlsX509KeyManager clientKeyManager = new AdvancedTlsX509KeyManager();
313311
clientKeyManager.updateIdentityCredentials(clientKey0, clientCert0);
@@ -359,7 +357,6 @@ public void onFileReloadingKeyManagerTrustManagerTest() throws Exception {
359357
.clientAuth(ClientAuth.REQUIRE).build();
360358
server = Grpc.newServerBuilderForPort(0, serverCredentials).addService(
361359
new SimpleServiceImpl()).build().start();
362-
TimeUnit.SECONDS.sleep(5);
363360
// Create a client to connect.
364361
AdvancedTlsX509KeyManager clientKeyManager = new AdvancedTlsX509KeyManager();
365362
Closeable clientKeyShutdown = clientKeyManager.updateIdentityCredentialsFromFile(clientKey0File,
@@ -391,6 +388,28 @@ public void onFileReloadingKeyManagerTrustManagerTest() throws Exception {
391388
clientTrustShutdown.close();
392389
}
393390

391+
@Test
392+
public void onFileReloadingKeyManagerBadInitialContentTest() throws Exception {
393+
exceptionRule.expect(GeneralSecurityException.class);
394+
AdvancedTlsX509KeyManager keyManager = new AdvancedTlsX509KeyManager();
395+
// We swap the order of key and certificates to intentionally create an exception.
396+
Closeable keyShutdown = keyManager.updateIdentityCredentialsFromFile(serverCert0File,
397+
serverKey0File, 100, TimeUnit.MILLISECONDS, executor);
398+
keyShutdown.close();
399+
}
400+
401+
@Test
402+
public void onFileReloadingTrustManagerBadInitialContentTest() throws Exception {
403+
exceptionRule.expect(GeneralSecurityException.class);
404+
AdvancedTlsX509TrustManager trustManager = AdvancedTlsX509TrustManager.newBuilder()
405+
.setVerification(Verification.CERTIFICATE_ONLY_VERIFICATION)
406+
.build();
407+
// We pass in a key as the trust certificates to intentionally create an exception.
408+
Closeable trustShutdown = trustManager.updateTrustCredentialsFromFile(serverKey0File,
409+
100, TimeUnit.MILLISECONDS, executor);
410+
trustShutdown.close();
411+
}
412+
394413
@Test
395414
public void keyManagerAliasesTest() throws Exception {
396415
AdvancedTlsX509KeyManager km = new AdvancedTlsX509KeyManager();

0 commit comments

Comments
 (0)