embulk-input-gcs 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/secretkeys.tar DELETED
Binary file
data/secretkeys.tar.enc DELETED
Binary file
@@ -1,206 +0,0 @@
1
- package org.embulk.input.gcs;
2
-
3
- import com.google.api.client.auth.oauth2.TokenResponseException;
4
- import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
5
- import com.google.api.client.googleapis.compute.ComputeCredential;
6
- import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
7
- import com.google.api.client.googleapis.json.GoogleJsonResponseException;
8
- import com.google.api.client.http.HttpRequestInitializer;
9
- import com.google.api.client.http.HttpTransport;
10
- import com.google.api.client.json.JsonFactory;
11
- import com.google.api.client.json.jackson2.JacksonFactory;
12
- import com.google.api.services.storage.Storage;
13
- import com.google.api.services.storage.StorageScopes;
14
- import com.google.common.base.Throwables;
15
- import com.google.common.collect.ImmutableList;
16
- import org.embulk.config.ConfigException;
17
- import org.embulk.spi.Exec;
18
- import org.embulk.spi.util.RetryExecutor.RetryGiveupException;
19
- import org.embulk.spi.util.RetryExecutor.Retryable;
20
- import org.slf4j.Logger;
21
- import static org.embulk.spi.util.RetryExecutor.retryExecutor;
22
-
23
- import java.io.File;
24
- import java.io.FileInputStream;
25
-
26
- import java.io.IOException;
27
- import java.io.InterruptedIOException;
28
- import java.security.GeneralSecurityException;
29
- import java.util.Collections;
30
- import java.util.Optional;
31
-
32
- public class GcsAuthentication
33
- {
34
- private final Logger log = Exec.getLogger(GcsAuthentication.class);
35
- private final Optional<String> serviceAccountEmail;
36
- private final Optional<String> p12KeyFilePath;
37
- private final Optional<String> jsonKeyFilePath;
38
- private final String applicationName;
39
- private final HttpTransport httpTransport;
40
- private final JsonFactory jsonFactory;
41
- private final HttpRequestInitializer credentials;
42
-
43
- public GcsAuthentication(String authMethod, Optional<String> serviceAccountEmail,
44
- Optional<String> p12KeyFilePath, Optional<String> jsonKeyFilePath, String applicationName)
45
- throws IOException, GeneralSecurityException
46
- {
47
- this.serviceAccountEmail = serviceAccountEmail;
48
- this.p12KeyFilePath = p12KeyFilePath;
49
- this.jsonKeyFilePath = jsonKeyFilePath;
50
- this.applicationName = applicationName;
51
-
52
- this.httpTransport = GoogleNetHttpTransport.newTrustedTransport();
53
- this.jsonFactory = new JacksonFactory();
54
-
55
- if (authMethod.equals("compute_engine")) {
56
- this.credentials = getComputeCredential();
57
- }
58
- else if (authMethod.toLowerCase().equals("json_key")) {
59
- this.credentials = getServiceAccountCredentialFromJsonFile();
60
- }
61
- else {
62
- this.credentials = getServiceAccountCredential();
63
- }
64
- }
65
-
66
- /**
67
- * @see https://developers.google.com/accounts/docs/OAuth2ServiceAccount#authorizingrequests
68
- */
69
- private GoogleCredential getServiceAccountCredential() throws IOException, GeneralSecurityException
70
- {
71
- // @see https://cloud.google.com/compute/docs/api/how-tos/authorization
72
- // @see https://developers.google.com/resources/api-libraries/documentation/storage/v1/java/latest/com/google/api/services/storage/STORAGE_SCOPE.html
73
- // @see https://developers.google.com/resources/api-libraries/documentation/bigquery/v2/java/latest/com/google/api/services/bigquery/BigqueryScopes.html
74
- return new GoogleCredential.Builder()
75
- .setTransport(httpTransport)
76
- .setJsonFactory(jsonFactory)
77
- .setServiceAccountId(serviceAccountEmail.orElseGet(null))
78
- .setServiceAccountScopes(
79
- ImmutableList.of(
80
- StorageScopes.DEVSTORAGE_READ_ONLY
81
- )
82
- )
83
- .setServiceAccountPrivateKeyFromP12File(new File(p12KeyFilePath.get()))
84
- .build();
85
- }
86
-
87
- private GoogleCredential getServiceAccountCredentialFromJsonFile() throws IOException
88
- {
89
- FileInputStream stream = new FileInputStream(jsonKeyFilePath.get());
90
-
91
- return GoogleCredential.fromStream(stream, httpTransport, jsonFactory)
92
- .createScoped(Collections.singleton(StorageScopes.DEVSTORAGE_READ_ONLY));
93
- }
94
-
95
- /**
96
- * @see http://developers.guge.io/accounts/docs/OAuth2ServiceAccount#creatinganaccount
97
- * @see https://developers.google.com/accounts/docs/OAuth2
98
- */
99
- private ComputeCredential getComputeCredential() throws IOException
100
- {
101
- ComputeCredential credential = new ComputeCredential.Builder(httpTransport, jsonFactory)
102
- .build();
103
- credential.refreshToken();
104
-
105
- return credential;
106
- }
107
-
108
- public Storage getGcsClient(final String bucket, int maxConnectionRetry) throws ConfigException, IOException
109
- {
110
- try {
111
- return retryExecutor()
112
- .withRetryLimit(maxConnectionRetry)
113
- .withInitialRetryWait(500)
114
- .withMaxRetryWait(30 * 1000)
115
- .runInterruptible(new Retryable<Storage>() {
116
- @Override
117
- public Storage call() throws IOException, RetryGiveupException
118
- {
119
- Storage client = new Storage.Builder(httpTransport, jsonFactory, credentials)
120
- .setApplicationName(applicationName)
121
- .build();
122
-
123
- // For throw ConfigException when authentication is fail.
124
- long maxResults = 1;
125
- client.objects().list(bucket).setMaxResults(maxResults).execute();
126
-
127
- return client;
128
- }
129
-
130
- @Override
131
- public boolean isRetryableException(Exception exception)
132
- {
133
- if (exception instanceof GoogleJsonResponseException) {
134
- if (((GoogleJsonResponseException) exception).getDetails() == null) {
135
- if (((GoogleJsonResponseException) exception).getContent() != null) {
136
- String content = ((GoogleJsonResponseException) exception).getContent();
137
- log.warn("Invalid response was returned : {}", content);
138
- return true;
139
- }
140
- }
141
- int statusCode = ((GoogleJsonResponseException) exception).getDetails().getCode();
142
- return !(statusCode / 100 == 4);
143
- }
144
- else if (exception instanceof TokenResponseException) {
145
- TokenResponseException ex = (TokenResponseException) exception;
146
- if (ex.getDetails() != null && ex.getDetails().getErrorDescription() != null) {
147
- String errorDescription = ex.getDetails().getErrorDescription();
148
- // Retry: 400 BadRequest "Invalid JWT..."
149
- // Caused by: com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
150
- // {
151
- // "error" : "invalid_grant",
152
- // "error_description" : "Invalid JWT: No valid verifier found for issuer."
153
- // }
154
- if (errorDescription.contains("Invalid JWT")) {
155
- log.warn("Invalid response was returned : {}", errorDescription);
156
- return true;
157
- }
158
- }
159
- return !(ex.getStatusCode() / 100 == 4);
160
- }
161
- return true;
162
- }
163
-
164
- @Override
165
- public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait)
166
- throws RetryGiveupException
167
- {
168
- String message = String.format("GCS GET request failed. Retrying %d/%d after %d seconds. Message: %s: %s",
169
- retryCount, retryLimit, retryWait / 1000, exception.getClass(), exception.getMessage());
170
- if (retryCount % 3 == 0) {
171
- log.warn(message, exception);
172
- }
173
- else {
174
- log.warn(message);
175
- }
176
- }
177
-
178
- @Override
179
- public void onGiveup(Exception firstException, Exception lastException)
180
- throws RetryGiveupException
181
- {
182
- }
183
- });
184
- }
185
- catch (RetryGiveupException ex) {
186
- if (ex.getCause() instanceof GoogleJsonResponseException || ex.getCause() instanceof TokenResponseException) {
187
- int statusCode = 0;
188
- if (ex.getCause() instanceof GoogleJsonResponseException) {
189
- if (((GoogleJsonResponseException) ex.getCause()).getDetails() != null) {
190
- statusCode = ((GoogleJsonResponseException) ex.getCause()).getDetails().getCode();
191
- }
192
- }
193
- else if (ex.getCause() instanceof TokenResponseException) {
194
- statusCode = ((TokenResponseException) ex.getCause()).getStatusCode();
195
- }
196
- if (statusCode / 100 == 4) {
197
- throw new ConfigException(ex);
198
- }
199
- }
200
- throw Throwables.propagate(ex);
201
- }
202
- catch (InterruptedException ex) {
203
- throw new InterruptedIOException();
204
- }
205
- }
206
- }
@@ -1,185 +0,0 @@
1
- package org.embulk.input.gcs;
2
-
3
- import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
4
- import com.google.api.services.storage.Storage;
5
- import org.embulk.EmbulkTestRuntime;
6
- import org.embulk.config.ConfigException;
7
- import org.junit.BeforeClass;
8
- import org.junit.Rule;
9
- import org.junit.Test;
10
-
11
- import java.io.FileNotFoundException;
12
-
13
- import java.io.IOException;
14
- import java.lang.reflect.Field;
15
- import java.security.GeneralSecurityException;
16
- import java.util.Optional;
17
-
18
- import static org.junit.Assert.assertEquals;
19
- import static org.junit.Assume.assumeNotNull;
20
-
21
- public class TestGcsAuthentication
22
- {
23
- private static Optional<String> GCP_EMAIL;
24
- private static Optional<String> GCP_P12_KEYFILE;
25
- private static Optional<String> GCP_JSON_KEYFILE;
26
- private static String GCP_BUCKET;
27
- private static final String GCP_APPLICATION_NAME = "embulk-input-gcs";
28
- private static int MAX_CONNECTION_RETRY = 3;
29
-
30
- /*
31
- * This test case requires environment variables
32
- * GCP_EMAIL
33
- * GCP_P12_KEYFILE
34
- * GCP_JSON_KEYFILE
35
- * GCP_BUCKET
36
- */
37
- @BeforeClass
38
- public static void initializeConstant()
39
- {
40
- String gcpEmail = System.getenv("GCP_EMAIL");
41
- String gcpP12KeyFile = System.getenv("GCP_P12_KEYFILE");
42
- String gcpJsonKeyFile = System.getenv("GCP_JSON_KEYFILE");
43
- String gcpBucket = System.getenv("GCP_BUCKET");
44
-
45
- // skip test cases, if environment variables are not set.
46
- assumeNotNull(gcpEmail, gcpP12KeyFile, gcpJsonKeyFile, gcpBucket);
47
-
48
- GCP_EMAIL = Optional.of(gcpEmail);
49
- GCP_P12_KEYFILE = Optional.of(gcpP12KeyFile);
50
- GCP_JSON_KEYFILE = Optional.of(gcpJsonKeyFile);
51
- GCP_BUCKET = gcpBucket;
52
- }
53
-
54
- @Rule
55
- public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
56
-
57
- @Test
58
- public void testGetServiceAccountCredentialSuccess()
59
- throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
60
- {
61
- GcsAuthentication auth = new GcsAuthentication(
62
- "private_key",
63
- GCP_EMAIL,
64
- GCP_P12_KEYFILE,
65
- null,
66
- GCP_APPLICATION_NAME
67
- );
68
-
69
- Field field = GcsAuthentication.class.getDeclaredField("credentials");
70
- field.setAccessible(true);
71
-
72
- assertEquals(GoogleCredential.class, field.get(auth).getClass());
73
- }
74
-
75
- @Test(expected = FileNotFoundException.class)
76
- public void testGetServiceAccountCredentialThrowFileNotFoundException()
77
- throws GeneralSecurityException, IOException
78
- {
79
- Optional<String> notFoundP12Keyfile = Optional.of("/path/to/notfound.p12");
80
- GcsAuthentication auth = new GcsAuthentication(
81
- "private_key",
82
- GCP_EMAIL,
83
- notFoundP12Keyfile,
84
- null,
85
- GCP_APPLICATION_NAME
86
- );
87
- }
88
-
89
- @Test
90
- public void testGetGcsClientUsingServiceAccountCredentialSuccess()
91
- throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
92
- {
93
- GcsAuthentication auth = new GcsAuthentication(
94
- "private_key",
95
- GCP_EMAIL,
96
- GCP_P12_KEYFILE,
97
- null,
98
- GCP_APPLICATION_NAME
99
- );
100
-
101
- Storage client = auth.getGcsClient(GCP_BUCKET, MAX_CONNECTION_RETRY);
102
-
103
- assertEquals(Storage.class, client.getClass());
104
- }
105
-
106
- @Test(expected = ConfigException.class)
107
- public void testGetGcsClientUsingServiceAccountCredentialThrowJsonResponseException()
108
- throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
109
- {
110
- GcsAuthentication auth = new GcsAuthentication(
111
- "private_key",
112
- GCP_EMAIL,
113
- GCP_P12_KEYFILE,
114
- null,
115
- GCP_APPLICATION_NAME
116
- );
117
-
118
- Storage client = auth.getGcsClient("non-exists-bucket", MAX_CONNECTION_RETRY);
119
-
120
- assertEquals(Storage.class, client.getClass());
121
- }
122
-
123
- @Test
124
- public void testGetServiceAccountCredentialFromJsonFileSuccess()
125
- throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
126
- {
127
- GcsAuthentication auth = new GcsAuthentication(
128
- "json_key",
129
- GCP_EMAIL,
130
- null,
131
- GCP_JSON_KEYFILE,
132
- GCP_APPLICATION_NAME
133
- );
134
- Field field = GcsAuthentication.class.getDeclaredField("credentials");
135
- field.setAccessible(true);
136
-
137
- assertEquals(GoogleCredential.class, field.get(auth).getClass());
138
- }
139
-
140
- @Test(expected = FileNotFoundException.class)
141
- public void testGetServiceAccountCredentialFromJsonThrowFileFileNotFoundException()
142
- throws GeneralSecurityException, IOException
143
- {
144
- Optional<String> notFoundJsonKeyfile = Optional.of("/path/to/notfound.json");
145
- GcsAuthentication auth = new GcsAuthentication(
146
- "json_key",
147
- GCP_EMAIL,
148
- null,
149
- notFoundJsonKeyfile,
150
- GCP_APPLICATION_NAME
151
- );
152
- }
153
-
154
- @Test
155
- public void testGetServiceAccountCredentialFromJsonSuccess()
156
- throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
157
- {
158
- GcsAuthentication auth = new GcsAuthentication(
159
- "json_key",
160
- GCP_EMAIL,
161
- null,
162
- GCP_JSON_KEYFILE,
163
- GCP_APPLICATION_NAME
164
- );
165
-
166
- Storage client = auth.getGcsClient(GCP_BUCKET, MAX_CONNECTION_RETRY);
167
-
168
- assertEquals(Storage.class, client.getClass());
169
- }
170
-
171
- @Test(expected = ConfigException.class)
172
- public void testGetServiceAccountCredentialFromJsonThrowGoogleJsonResponseException()
173
- throws NoSuchFieldException, IllegalAccessException, GeneralSecurityException, IOException
174
- {
175
- GcsAuthentication auth = new GcsAuthentication(
176
- "json_key",
177
- GCP_EMAIL,
178
- null,
179
- GCP_JSON_KEYFILE,
180
- GCP_APPLICATION_NAME
181
- );
182
-
183
- Storage client = auth.getGcsClient("non-exists-bucket", MAX_CONNECTION_RETRY);
184
- }
185
- }
Binary file