PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/repository-gcs/src/test/java/org/elasticsearch/repositories/gcs/GoogleCloudStorageClientSettingsTests.java

https://github.com/elasticsearch/elasticsearch
Java | 273 lines | 234 code | 29 blank | 10 comment | 19 complexity | 7354d64dc2f43ee94d661a4d98d9e74c MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
  3. * or more contributor license agreements. Licensed under the Elastic License
  4. * 2.0 and the Server Side Public License, v 1; you may not use this file except
  5. * in compliance with, at your election, the Elastic License 2.0 or the Server
  6. * Side Public License, v 1.
  7. */
  8. package org.elasticsearch.repositories.gcs;
  9. import com.google.api.services.storage.StorageScopes;
  10. import com.google.auth.oauth2.ServiceAccountCredentials;
  11. import org.elasticsearch.common.settings.MockSecureSettings;
  12. import org.elasticsearch.common.settings.Setting;
  13. import org.elasticsearch.common.settings.Settings;
  14. import org.elasticsearch.core.TimeValue;
  15. import org.elasticsearch.core.Tuple;
  16. import org.elasticsearch.test.ESTestCase;
  17. import java.net.InetAddress;
  18. import java.net.InetSocketAddress;
  19. import java.net.Proxy;
  20. import java.net.URI;
  21. import java.nio.charset.StandardCharsets;
  22. import java.security.KeyPair;
  23. import java.security.KeyPairGenerator;
  24. import java.util.ArrayList;
  25. import java.util.Base64;
  26. import java.util.Collections;
  27. import java.util.HashMap;
  28. import java.util.List;
  29. import java.util.Locale;
  30. import java.util.Map;
  31. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.APPLICATION_NAME_SETTING;
  32. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.CONNECT_TIMEOUT_SETTING;
  33. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.CREDENTIALS_FILE_SETTING;
  34. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.ENDPOINT_SETTING;
  35. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.PROJECT_ID_SETTING;
  36. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.PROXY_HOST_SETTING;
  37. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.PROXY_PORT_SETTING;
  38. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.PROXY_TYPE_SETTING;
  39. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.READ_TIMEOUT_SETTING;
  40. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.getClientSettings;
  41. import static org.elasticsearch.repositories.gcs.GoogleCloudStorageClientSettings.loadCredential;
  42. public class GoogleCloudStorageClientSettingsTests extends ESTestCase {
  43. public void testLoadWithEmptySettings() {
  44. final Map<String, GoogleCloudStorageClientSettings> clientsSettings = GoogleCloudStorageClientSettings.load(Settings.EMPTY);
  45. assertEquals(1, clientsSettings.size());
  46. assertNotNull(clientsSettings.get("default"));
  47. }
  48. public void testLoad() throws Exception {
  49. final int nbClients = randomIntBetween(1, 5);
  50. final List<Setting<?>> deprecationWarnings = new ArrayList<>();
  51. final Tuple<Map<String, GoogleCloudStorageClientSettings>, Settings> randomClients = randomClients(nbClients, deprecationWarnings);
  52. final Map<String, GoogleCloudStorageClientSettings> expectedClientsSettings = randomClients.v1();
  53. final Map<String, GoogleCloudStorageClientSettings> actualClientsSettings = GoogleCloudStorageClientSettings.load(
  54. randomClients.v2()
  55. );
  56. assertEquals(expectedClientsSettings.size(), actualClientsSettings.size());
  57. for (final String clientName : expectedClientsSettings.keySet()) {
  58. final GoogleCloudStorageClientSettings actualClientSettings = actualClientsSettings.get(clientName);
  59. assertNotNull(actualClientSettings);
  60. final GoogleCloudStorageClientSettings expectedClientSettings = expectedClientsSettings.get(clientName);
  61. assertNotNull(expectedClientSettings);
  62. assertGoogleCredential(expectedClientSettings.getCredential(), actualClientSettings.getCredential());
  63. assertEquals(expectedClientSettings.getHost(), actualClientSettings.getHost());
  64. assertEquals(expectedClientSettings.getProjectId(), actualClientSettings.getProjectId());
  65. assertEquals(expectedClientSettings.getConnectTimeout(), actualClientSettings.getConnectTimeout());
  66. assertEquals(expectedClientSettings.getReadTimeout(), actualClientSettings.getReadTimeout());
  67. assertEquals(expectedClientSettings.getApplicationName(), actualClientSettings.getApplicationName());
  68. }
  69. if (deprecationWarnings.isEmpty() == false) {
  70. assertSettingDeprecationsAndWarnings(deprecationWarnings.toArray(new Setting<?>[0]));
  71. }
  72. }
  73. public void testLoadCredential() throws Exception {
  74. final List<Setting<?>> deprecationWarnings = new ArrayList<>();
  75. final Tuple<Map<String, GoogleCloudStorageClientSettings>, Settings> randomClient = randomClients(1, deprecationWarnings);
  76. final GoogleCloudStorageClientSettings expectedClientSettings = randomClient.v1().values().iterator().next();
  77. final String clientName = randomClient.v1().keySet().iterator().next();
  78. assertGoogleCredential(expectedClientSettings.getCredential(), loadCredential(randomClient.v2(), clientName));
  79. }
  80. public void testProjectIdDefaultsToCredentials() throws Exception {
  81. final String clientName = randomAlphaOfLength(5);
  82. final Tuple<ServiceAccountCredentials, byte[]> credentials = randomCredential(clientName);
  83. final ServiceAccountCredentials credential = credentials.v1();
  84. final GoogleCloudStorageClientSettings googleCloudStorageClientSettings = new GoogleCloudStorageClientSettings(
  85. credential,
  86. ENDPOINT_SETTING.getDefault(Settings.EMPTY),
  87. PROJECT_ID_SETTING.getDefault(Settings.EMPTY),
  88. CONNECT_TIMEOUT_SETTING.getDefault(Settings.EMPTY),
  89. READ_TIMEOUT_SETTING.getDefault(Settings.EMPTY),
  90. APPLICATION_NAME_SETTING.getDefault(Settings.EMPTY),
  91. new URI(""),
  92. PROXY_TYPE_SETTING.getDefault(Settings.EMPTY),
  93. PROXY_HOST_SETTING.getDefault(Settings.EMPTY),
  94. PROXY_PORT_SETTING.getDefault(Settings.EMPTY)
  95. );
  96. assertEquals(credential.getProjectId(), googleCloudStorageClientSettings.getProjectId());
  97. }
  98. public void testLoadsProxySettings() throws Exception {
  99. final String clientName = randomAlphaOfLength(5);
  100. final ServiceAccountCredentials credential = randomCredential(clientName).v1();
  101. final GoogleCloudStorageClientSettings googleCloudStorageClientSettings = new GoogleCloudStorageClientSettings(
  102. credential,
  103. ENDPOINT_SETTING.getDefault(Settings.EMPTY),
  104. PROJECT_ID_SETTING.getDefault(Settings.EMPTY),
  105. CONNECT_TIMEOUT_SETTING.getDefault(Settings.EMPTY),
  106. READ_TIMEOUT_SETTING.getDefault(Settings.EMPTY),
  107. APPLICATION_NAME_SETTING.getDefault(Settings.EMPTY),
  108. new URI(""),
  109. Proxy.Type.HTTP,
  110. "192.168.15.1",
  111. 8080
  112. );
  113. assertEquals(
  114. new Proxy(Proxy.Type.HTTP, new InetSocketAddress(InetAddress.getByName("192.168.15.1"), 8080)),
  115. googleCloudStorageClientSettings.getProxy()
  116. );
  117. }
  118. /** Generates a given number of GoogleCloudStorageClientSettings along with the Settings to build them from **/
  119. private Tuple<Map<String, GoogleCloudStorageClientSettings>, Settings> randomClients(
  120. final int nbClients,
  121. final List<Setting<?>> deprecationWarnings
  122. ) throws Exception {
  123. final Map<String, GoogleCloudStorageClientSettings> expectedClients = new HashMap<>();
  124. final Settings.Builder settings = Settings.builder();
  125. final MockSecureSettings secureSettings = new MockSecureSettings();
  126. for (int i = 0; i < nbClients; i++) {
  127. final String clientName = randomAlphaOfLength(5).toLowerCase(Locale.ROOT);
  128. final GoogleCloudStorageClientSettings clientSettings = randomClient(clientName, settings, secureSettings, deprecationWarnings);
  129. expectedClients.put(clientName, clientSettings);
  130. }
  131. if (randomBoolean()) {
  132. final GoogleCloudStorageClientSettings clientSettings = randomClient("default", settings, secureSettings, deprecationWarnings);
  133. expectedClients.put("default", clientSettings);
  134. } else {
  135. expectedClients.put("default", getClientSettings(Settings.EMPTY, "default"));
  136. }
  137. return Tuple.tuple(expectedClients, settings.setSecureSettings(secureSettings).build());
  138. }
  139. /** Generates a random GoogleCloudStorageClientSettings along with the Settings to build it **/
  140. private static GoogleCloudStorageClientSettings randomClient(
  141. final String clientName,
  142. final Settings.Builder settings,
  143. final MockSecureSettings secureSettings,
  144. final List<Setting<?>> deprecationWarnings
  145. ) throws Exception {
  146. final Tuple<ServiceAccountCredentials, byte[]> credentials = randomCredential(clientName);
  147. final ServiceAccountCredentials credential = credentials.v1();
  148. secureSettings.setFile(CREDENTIALS_FILE_SETTING.getConcreteSettingForNamespace(clientName).getKey(), credentials.v2());
  149. String endpoint;
  150. if (randomBoolean()) {
  151. endpoint = randomFrom(
  152. "http://www.elastic.co",
  153. "http://metadata.google.com:88/oauth",
  154. "https://www.googleapis.com",
  155. "https://www.elastic.co:443",
  156. "http://localhost:8443",
  157. "https://www.googleapis.com/oauth/token"
  158. );
  159. settings.put(ENDPOINT_SETTING.getConcreteSettingForNamespace(clientName).getKey(), endpoint);
  160. } else {
  161. endpoint = ENDPOINT_SETTING.getDefault(Settings.EMPTY);
  162. }
  163. String projectId;
  164. if (randomBoolean()) {
  165. projectId = randomAlphaOfLength(5);
  166. settings.put(PROJECT_ID_SETTING.getConcreteSettingForNamespace(clientName).getKey(), projectId);
  167. } else {
  168. projectId = PROJECT_ID_SETTING.getDefault(Settings.EMPTY);
  169. }
  170. TimeValue connectTimeout;
  171. if (randomBoolean()) {
  172. connectTimeout = randomTimeout();
  173. settings.put(CONNECT_TIMEOUT_SETTING.getConcreteSettingForNamespace(clientName).getKey(), connectTimeout.getStringRep());
  174. } else {
  175. connectTimeout = CONNECT_TIMEOUT_SETTING.getDefault(Settings.EMPTY);
  176. }
  177. TimeValue readTimeout;
  178. if (randomBoolean()) {
  179. readTimeout = randomTimeout();
  180. settings.put(READ_TIMEOUT_SETTING.getConcreteSettingForNamespace(clientName).getKey(), readTimeout.getStringRep());
  181. } else {
  182. readTimeout = READ_TIMEOUT_SETTING.getDefault(Settings.EMPTY);
  183. }
  184. String applicationName;
  185. if (randomBoolean()) {
  186. applicationName = randomAlphaOfLength(5);
  187. settings.put(APPLICATION_NAME_SETTING.getConcreteSettingForNamespace(clientName).getKey(), applicationName);
  188. deprecationWarnings.add(APPLICATION_NAME_SETTING.getConcreteSettingForNamespace(clientName));
  189. } else {
  190. applicationName = APPLICATION_NAME_SETTING.getDefault(Settings.EMPTY);
  191. }
  192. return new GoogleCloudStorageClientSettings(
  193. credential,
  194. endpoint,
  195. projectId,
  196. connectTimeout,
  197. readTimeout,
  198. applicationName,
  199. new URI(""),
  200. PROXY_TYPE_SETTING.getDefault(Settings.EMPTY),
  201. PROXY_HOST_SETTING.getDefault(Settings.EMPTY),
  202. PROXY_PORT_SETTING.getDefault(Settings.EMPTY)
  203. );
  204. }
  205. /** Generates a random GoogleCredential along with its corresponding Service Account file provided as a byte array **/
  206. private static Tuple<ServiceAccountCredentials, byte[]> randomCredential(final String clientName) throws Exception {
  207. final KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
  208. final ServiceAccountCredentials.Builder credentialBuilder = ServiceAccountCredentials.newBuilder();
  209. credentialBuilder.setClientId("id_" + clientName);
  210. credentialBuilder.setClientEmail(clientName);
  211. credentialBuilder.setProjectId("project_id_" + clientName);
  212. credentialBuilder.setPrivateKey(keyPair.getPrivate());
  213. credentialBuilder.setPrivateKeyId("private_key_id_" + clientName);
  214. credentialBuilder.setScopes(Collections.singleton(StorageScopes.DEVSTORAGE_FULL_CONTROL));
  215. final String encodedPrivateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
  216. final String serviceAccount = """
  217. {
  218. "type": "service_account",
  219. "project_id": "project_id_%s",
  220. "private_key_id": "private_key_id_%s",
  221. "private_key": "-----BEGIN PRIVATE KEY-----\\n%s\\n-----END PRIVATE KEY-----\\n",
  222. "client_email": "%s",
  223. "client_id": "id_%s"
  224. }""".formatted(clientName, clientName, encodedPrivateKey, clientName, clientName);
  225. return Tuple.tuple(credentialBuilder.build(), serviceAccount.getBytes(StandardCharsets.UTF_8));
  226. }
  227. private static TimeValue randomTimeout() {
  228. return randomFrom(TimeValue.MINUS_ONE, TimeValue.ZERO, TimeValue.parseTimeValue(randomPositiveTimeValue(), "test"));
  229. }
  230. private static void assertGoogleCredential(ServiceAccountCredentials expected, ServiceAccountCredentials actual) {
  231. if (expected != null) {
  232. assertEquals(expected.getServiceAccountUser(), actual.getServiceAccountUser());
  233. assertEquals(expected.getClientId(), actual.getClientId());
  234. assertEquals(expected.getClientEmail(), actual.getClientEmail());
  235. assertEquals(expected.getAccount(), actual.getAccount());
  236. assertEquals(expected.getProjectId(), actual.getProjectId());
  237. assertEquals(expected.getScopes(), actual.getScopes());
  238. assertEquals(expected.getPrivateKey(), actual.getPrivateKey());
  239. assertEquals(expected.getPrivateKeyId(), actual.getPrivateKeyId());
  240. } else {
  241. assertNull(actual);
  242. }
  243. }
  244. }