/
MtlsUtils.java
150 lines (127 loc) · 4.64 KB
/
MtlsUtils.java
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
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.api.client.googleapis.util;
import com.google.api.client.json.GenericJson;
import com.google.api.client.json.JsonParser;
import com.google.api.client.util.Beta;
import com.google.api.client.util.Key;
import com.google.api.client.util.SecurityUtils;
import com.google.common.annotations.VisibleForTesting;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.util.List;
public class MtlsUtils {
public interface MtlsProvider {
boolean useMtlsClientCertificate();
String getKeyStorePassword();
KeyStore loadDefaultKeyStore() throws IOException, GeneralSecurityException;
}
/**
* {@link Beta} <br>
* Data class representing context_aware_metadata.json file.
*
* @since 1.31
*/
@Beta
public static class ContextAwareMetadataJson extends GenericJson {
/** Cert provider command */
@Key("cert_provider_command")
private List<String> commands;
/**
* Returns the cert provider command.
*
* @since 1.31
*/
public final List<String> getCommands() {
return commands;
}
}
@VisibleForTesting
static class DefaultMtlsProvider implements MtlsProvider {
private static final String DEFAULT_CONTEXT_AWARE_METADATA_PATH =
System.getProperty("user.home") + "/.secureConnect/context_aware_metadata.json";
/** GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable */
public static final String GOOGLE_API_USE_CLIENT_CERTIFICATE =
"GOOGLE_API_USE_CLIENT_CERTIFICATE";
interface EnvironmentProvider {
String getenv(String name);
}
static class SystemEnvironmentProvider implements EnvironmentProvider {
@Override
public String getenv(String name) {
return System.getenv(name);
}
}
DefaultMtlsProvider() {
this(new SystemEnvironmentProvider(), DEFAULT_CONTEXT_AWARE_METADATA_PATH);
}
private EnvironmentProvider envProvider;
private String metadataPath;
@VisibleForTesting
DefaultMtlsProvider(EnvironmentProvider envProvider, String metadataPath) {
this.envProvider = envProvider;
this.metadataPath = metadataPath;
}
@Override
public boolean useMtlsClientCertificate() {
String useClientCertificate = envProvider.getenv(GOOGLE_API_USE_CLIENT_CERTIFICATE);
return "true".equals(useClientCertificate);
}
@Override
public String getKeyStorePassword() {
return "";
}
@Override
public KeyStore loadDefaultKeyStore() throws IOException, GeneralSecurityException {
// Load the cert provider command from the json file.
InputStream stream;
try {
stream = new FileInputStream(metadataPath);
} catch (FileNotFoundException ignored) {
// file doesn't exist
return null;
}
List<String> command = extractCertificateProviderCommand(stream);
// Call the command.
Process process = new ProcessBuilder(command).start();
int exitCode = -1;
try {
exitCode = process.waitFor();
} catch (InterruptedException e) {
throw new IOException("Interrupted executing certificate provider command", e);
}
if (exitCode != 0) {
throw new IOException(
String.format("Failed to execute cert provider command with exit code: %d", exitCode));
}
// Parse input certificates from shell command
return SecurityUtils.createMtlsKeyStore(process.getInputStream());
}
@VisibleForTesting
static List<String> extractCertificateProviderCommand(InputStream contextAwareMetadata)
throws IOException {
JsonParser parser = Utils.getDefaultJsonFactory().createJsonParser(contextAwareMetadata);
ContextAwareMetadataJson json = parser.parse(ContextAwareMetadataJson.class);
return json.getCommands();
}
}
private static final MtlsProvider MTLS_PROVIDER = new DefaultMtlsProvider();
public static MtlsProvider getDefaultMtlsProvider() {
return MTLS_PROVIDER;
}
}