Skip to content

Commit d09ec5a

Browse files
committed
Address PR comments
1 parent 7a2b2ce commit d09ec5a

File tree

4 files changed

+45
-58
lines changed

4 files changed

+45
-58
lines changed

oauth2_http/java/com/google/auth/mtls/DefaultMtlsProviderFactory.java

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,15 @@ public class DefaultMtlsProviderFactory {
4646
* @throws IOException if an I/O error occurs during provider creation.
4747
*/
4848
public static MtlsProvider create() throws IOException {
49-
MtlsProvider mtlsProvider;
50-
try {
51-
mtlsProvider = new X509Provider();
52-
mtlsProvider.getKeyStore();
49+
MtlsProvider mtlsProvider = new X509Provider();
50+
if (mtlsProvider.isCertificateSourceAvailable()) {
5351
return mtlsProvider;
54-
} catch (CertificateSourceUnavailableException e) {
55-
try {
56-
mtlsProvider = new SecureConnectProvider();
57-
mtlsProvider.getKeyStore();
58-
return mtlsProvider;
59-
} catch (CertificateSourceUnavailableException ex) {
60-
throw new CertificateSourceUnavailableException(
61-
"No MtlsSource is available on this device.");
62-
}
6352
}
53+
mtlsProvider = new SecureConnectProvider();
54+
if (mtlsProvider.isCertificateSourceAvailable()) {
55+
return mtlsProvider;
56+
}
57+
throw new CertificateSourceUnavailableException(
58+
"No Certificate Source is available on this device.");
6459
}
6560
}

oauth2_http/java/com/google/auth/mtls/MtlsProvider.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,7 @@
4343
public interface MtlsProvider {
4444
/** Returns the mutual TLS key store. */
4545
KeyStore getKeyStore() throws IOException;
46+
47+
/** Returns true if the underlying certificate source is available. */
48+
boolean isCertificateSourceAvailable() throws IOException;
4649
}

oauth2_http/java/com/google/auth/mtls/SecureConnectProvider.java

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static class DefaultProcessProvider implements ProcessProvider {
6868
@Override
6969
public Process createProcess(InputStream metadata) throws IOException {
7070
if (metadata == null) {
71-
return null;
71+
throw new IOException("Error creating Process: metadata is null");
7272
}
7373
List<String> command = extractCertificateProviderCommand(metadata);
7474
return new ProcessBuilder(command).start();
@@ -108,12 +108,24 @@ public KeyStore getKeyStore() throws IOException {
108108
}
109109
}
110110

111+
@Override
112+
public boolean isCertificateSourceAvailable() throws IOException {
113+
try {
114+
this.getKeyStore();
115+
} catch (CertificateSourceUnavailableException e) {
116+
return false;
117+
}
118+
return true;
119+
}
120+
111121
@VisibleForTesting
112122
static KeyStore getKeyStore(InputStream metadata, ProcessProvider processProvider)
113123
throws IOException, InterruptedException, GeneralSecurityException {
114124
Process process = processProvider.createProcess(metadata);
115125

116126
// Run the command and timeout after 1000 milliseconds.
127+
// The cert provider command usually finishes instantly (if it doesn't hang),
128+
// so 1000 milliseconds is plenty of time.
117129
int exitCode = runCertificateProviderCommand(process, 1000);
118130
if (exitCode != 0) {
119131
throw new IOException("Cert provider command failed with exit code: " + exitCode);
@@ -134,28 +146,11 @@ static ImmutableList<String> extractCertificateProviderCommand(InputStream conte
134146
@VisibleForTesting
135147
static int runCertificateProviderCommand(Process commandProcess, long timeoutMilliseconds)
136148
throws IOException, InterruptedException {
137-
long startTime = System.currentTimeMillis();
138-
long remainTime = timeoutMilliseconds;
139-
140-
// In the while loop, keep checking if the process is terminated every 100 milliseconds
141-
// until timeout is reached or process is terminated. In getKeyStore we set timeout to
142-
// 1000 milliseconds, so 100 millisecond is a good number for the sleep.
143-
while (remainTime > 0) {
144-
Thread.sleep(Math.min(remainTime + 1, 100));
145-
remainTime -= System.currentTimeMillis() - startTime;
146-
147-
try {
148-
return commandProcess.exitValue();
149-
} catch (IllegalThreadStateException ignored) {
150-
// exitValue throws IllegalThreadStateException if process has not yet terminated.
151-
// Once the process is terminated, exitValue no longer throws exception. Therefore
152-
// in the while loop, we use exitValue to check if process is terminated. See
153-
// https://docs.oracle.com/javase/7/docs/api/java/lang/Process.html#exitValue()
154-
// for more details.
155-
}
149+
boolean terminated = commandProcess.waitFor(timeoutMilliseconds, TimeUnit.MILLISECONDS);
150+
if (!terminated) {
151+
commandProcess.destroy();
152+
throw new IOException("Cert provider command timed out");
156153
}
157-
158-
commandProcess.destroy();
159-
throw new IOException("cert provider command timed out");
154+
return commandProcess.exitValue();
160155
}
161156
}

oauth2_http/java/com/google/auth/mtls/X509Provider.java

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,12 @@ public KeyStore getKeyStore() throws IOException {
9393

9494
WorkloadCertificateConfiguration workloadCertConfig = getWorkloadCertificateConfiguration();
9595

96-
InputStream certStream = null;
97-
InputStream privateKeyStream = null;
98-
SequenceInputStream certAndPrivateKeyStream = null;
99-
try {
100-
// Read the certificate and private key file paths into separate streams.
101-
File certFile = new File(workloadCertConfig.getCertPath());
102-
File privateKeyFile = new File(workloadCertConfig.getPrivateKeyPath());
103-
certStream = createInputStream(certFile);
104-
privateKeyStream = createInputStream(privateKeyFile);
105-
106-
// Merge the two streams into a single stream.
107-
certAndPrivateKeyStream = new SequenceInputStream(certStream, privateKeyStream);
96+
// Read the certificate and private key file paths into streams.
97+
try (InputStream certStream = createInputStream(new File(workloadCertConfig.getCertPath()));
98+
InputStream privateKeyStream =
99+
createInputStream(new File(workloadCertConfig.getPrivateKeyPath()));
100+
SequenceInputStream certAndPrivateKeyStream =
101+
new SequenceInputStream(certStream, privateKeyStream)) {
108102

109103
// Build a key store using the combined stream.
110104
return SecurityUtils.createMtlsKeyStore(certAndPrivateKeyStream);
@@ -114,19 +108,19 @@ public KeyStore getKeyStore() throws IOException {
114108
} catch (Exception e) {
115109
// Wrap all other exception types to an IOException.
116110
throw new IOException(e);
117-
} finally {
118-
if (certStream != null) {
119-
certStream.close();
120-
}
121-
if (privateKeyStream != null) {
122-
privateKeyStream.close();
123-
}
124-
if (certAndPrivateKeyStream != null) {
125-
certAndPrivateKeyStream.close();
126-
}
127111
}
128112
}
129113

114+
@Override
115+
public boolean isCertificateSourceAvailable() throws IOException {
116+
try {
117+
this.getKeyStore();
118+
} catch (CertificateSourceUnavailableException e) {
119+
return false;
120+
}
121+
return true;
122+
}
123+
130124
private WorkloadCertificateConfiguration getWorkloadCertificateConfiguration()
131125
throws IOException {
132126
File certConfig;

0 commit comments

Comments
 (0)