embulk-output-ftp 0.1.0

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.
@@ -0,0 +1,285 @@
1
+ package org.embulk.output.ftp;
2
+
3
+ import org.bouncycastle.cert.X509CertificateHolder;
4
+ import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
5
+ import org.bouncycastle.openssl.PEMException;
6
+ import org.bouncycastle.openssl.PEMParser;
7
+ import sun.security.ssl.SSLSocketImpl;
8
+
9
+ import javax.net.ssl.KeyManager;
10
+ import javax.net.ssl.SSLContext;
11
+ import javax.net.ssl.SSLParameters;
12
+ import javax.net.ssl.SSLSocket;
13
+ import javax.net.ssl.SSLSocketFactory;
14
+ import javax.net.ssl.TrustManager;
15
+ import javax.net.ssl.TrustManagerFactory;
16
+ import javax.net.ssl.X509TrustManager;
17
+
18
+ import java.io.File;
19
+ import java.io.FileInputStream;
20
+ import java.io.IOException;
21
+ import java.io.Reader;
22
+ import java.net.InetAddress;
23
+ import java.net.Socket;
24
+ import java.net.UnknownHostException;
25
+ import java.security.InvalidAlgorithmParameterException;
26
+ import java.security.KeyManagementException;
27
+ import java.security.KeyStore;
28
+ import java.security.KeyStoreException;
29
+ import java.security.NoSuchAlgorithmException;
30
+ import java.security.SecureRandom;
31
+ import java.security.cert.CertificateException;
32
+ import java.security.cert.CertificateParsingException;
33
+ import java.security.cert.PKIXParameters;
34
+ import java.security.cert.TrustAnchor;
35
+ import java.security.cert.X509Certificate;
36
+ import java.util.ArrayList;
37
+ import java.util.List;
38
+
39
+ public class TrustManagers
40
+ {
41
+ private TrustManagers()
42
+ {
43
+ }
44
+
45
+ public static KeyStore readDefaultJavaKeyStore()
46
+ throws IOException, KeyStoreException, CertificateException
47
+ {
48
+ String path = (System.getProperty("java.home") + "/lib/security/cacerts").replace('/', File.separatorChar);
49
+ try {
50
+ KeyStore keyStore = KeyStore.getInstance("JKS");
51
+ try (FileInputStream in = new FileInputStream(path)) {
52
+ keyStore.load(in, null); // password=null because cacerts file is not encrypted
53
+ }
54
+ return keyStore;
55
+ }
56
+ catch (NoSuchAlgorithmException ex) {
57
+ throw new RuntimeException(ex); // TODO assertion exception?
58
+ }
59
+ }
60
+
61
+ public static List<X509Certificate> readDefaultJavaTrustedCertificates()
62
+ throws IOException, CertificateException, KeyStoreException, InvalidAlgorithmParameterException
63
+ {
64
+ KeyStore keyStore = readDefaultJavaKeyStore();
65
+ PKIXParameters params = new PKIXParameters(keyStore);
66
+ List<X509Certificate> certs = new ArrayList<>();
67
+ for (TrustAnchor trustAnchor : params.getTrustAnchors()) {
68
+ certs.add(trustAnchor.getTrustedCert());
69
+ }
70
+ return certs;
71
+ }
72
+
73
+ public static List<X509Certificate> readPemEncodedX509Certificates(Reader reader)
74
+ throws IOException, CertificateException
75
+ {
76
+ // this method abuses CertificateParsingException because its javadoc says
77
+ // CertificateParsingException is only for DER-encoded formats.
78
+
79
+ JcaX509CertificateConverter conv = new JcaX509CertificateConverter();
80
+ List<X509Certificate> certs = new ArrayList<>();
81
+
82
+ try {
83
+ PEMParser pemParser = new PEMParser(reader);
84
+ // PEMParser#close is unnecessary because it just closes underlying reader
85
+
86
+ while (true) {
87
+ Object pem = pemParser.readObject();
88
+
89
+ if (pem == null) {
90
+ break;
91
+ }
92
+
93
+ if (pem instanceof X509CertificateHolder) {
94
+ X509Certificate cert = conv.getCertificate((X509CertificateHolder) pem);
95
+ certs.add(cert);
96
+ }
97
+ }
98
+ }
99
+ catch (PEMException ex) {
100
+ // throw when parsing PemObject to Object fails
101
+ throw new CertificateParsingException(ex);
102
+ }
103
+ catch (IOException ex) {
104
+ if (ex.getClass().equals(IOException.class)) {
105
+ String message = ex.getMessage();
106
+ if (message.startsWith("unrecognised object: ")) {
107
+ // thrown at org.bouncycastle.openssl.PemParser.readObject when key type (header of a pem) is
108
+ // unknown.
109
+ throw new CertificateParsingException(ex);
110
+ }
111
+ else if (message.startsWith("-----END ") && message.endsWith(" not found")) {
112
+ // thrown at org.bouncycastle.util.io.pem.PemReader.loadObject when a pem file format is invalid
113
+ throw new CertificateParsingException(ex);
114
+ }
115
+ }
116
+ else {
117
+ throw ex;
118
+ }
119
+ }
120
+
121
+ return certs;
122
+ }
123
+
124
+ public static KeyStore buildKeyStoreFromTrustedCertificates(List<X509Certificate> certificates)
125
+ throws KeyStoreException
126
+ {
127
+ KeyStore keyStore = KeyStore.getInstance("JKS");
128
+ try {
129
+ keyStore.load(null);
130
+ }
131
+ catch (IOException | CertificateException | NoSuchAlgorithmException ex) {
132
+ throw new RuntimeException(ex);
133
+ }
134
+ int i = 0;
135
+ for (X509Certificate cert : certificates) {
136
+ keyStore.setCertificateEntry("cert_" + i, cert);
137
+ i++;
138
+ }
139
+ return keyStore;
140
+ }
141
+
142
+ public static X509TrustManager[] newTrustManager(List<X509Certificate> trustedCertificates)
143
+ throws KeyStoreException
144
+ {
145
+ try {
146
+ TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
147
+ KeyStore keyStore = buildKeyStoreFromTrustedCertificates(trustedCertificates);
148
+ factory.init(keyStore);
149
+ List<X509TrustManager> tms = new ArrayList<>();
150
+ for (TrustManager tm : factory.getTrustManagers()) {
151
+ if (tm instanceof X509TrustManager) {
152
+ tms.add((X509TrustManager) tm);
153
+ }
154
+ }
155
+ return tms.toArray(new X509TrustManager[tms.size()]);
156
+ }
157
+ catch (NoSuchAlgorithmException ex) {
158
+ throw new RuntimeException(ex); // TODO assertion exception?
159
+ }
160
+ }
161
+
162
+ public static X509TrustManager[] newDefaultJavaTrustManager()
163
+ throws IOException, CertificateException, KeyStoreException, InvalidAlgorithmParameterException
164
+ {
165
+ return newTrustManager(readDefaultJavaTrustedCertificates());
166
+ }
167
+
168
+ public static SSLContext newSSLContext(KeyManager[] keyManager, X509TrustManager[] trustManager)
169
+ throws KeyManagementException
170
+ {
171
+ try {
172
+ SSLContext context = SSLContext.getInstance("TLS");
173
+ context.init(
174
+ keyManager,
175
+ trustManager,
176
+ new SecureRandom());
177
+ return context;
178
+ }
179
+ catch (NoSuchAlgorithmException ex) {
180
+ throw new RuntimeException(ex);
181
+ }
182
+ }
183
+
184
+ public static SSLSocketFactory newSSLSocketFactory(KeyManager[] keyManager, X509TrustManager[] trustManager, String verifyHostname)
185
+ throws KeyManagementException
186
+ {
187
+ SSLContext context = newSSLContext(keyManager, trustManager);
188
+ SSLSocketFactory factory = context.getSocketFactory();
189
+ if (verifyHostname == null) {
190
+ return factory;
191
+ }
192
+ else {
193
+ return new VerifyHostNameSSLSocketFactory(factory, verifyHostname);
194
+ }
195
+ }
196
+
197
+ private static class VerifyHostNameSSLSocketFactory
198
+ extends SSLSocketFactory
199
+ {
200
+ private final SSLSocketFactory next;
201
+ private final String hostname;
202
+
203
+ public VerifyHostNameSSLSocketFactory(SSLSocketFactory next, String hostname)
204
+ {
205
+ this.next = next;
206
+ this.hostname = hostname;
207
+ }
208
+
209
+ @Override
210
+ public String[] getDefaultCipherSuites()
211
+ {
212
+ return next.getDefaultCipherSuites();
213
+ }
214
+
215
+ @Override
216
+ public String[] getSupportedCipherSuites()
217
+ {
218
+ return next.getSupportedCipherSuites();
219
+ }
220
+
221
+ @Override
222
+ public Socket createSocket(Socket s, String host, int port, boolean autoClose)
223
+ throws IOException
224
+ {
225
+ Socket sock = next.createSocket(s, host, port, autoClose);
226
+ setSSLParameters(sock, false);
227
+ return sock;
228
+ }
229
+
230
+ @Override
231
+ public Socket createSocket(String host, int port)
232
+ throws IOException, UnknownHostException
233
+ {
234
+ Socket sock = next.createSocket(host, port);
235
+ setSSLParameters(sock, false);
236
+ return sock;
237
+ }
238
+
239
+ @Override
240
+ public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
241
+ throws IOException, UnknownHostException
242
+ {
243
+ Socket sock = next.createSocket(host, port, localHost, localPort);
244
+ setSSLParameters(sock, false);
245
+ return sock;
246
+ }
247
+
248
+ @Override
249
+ public Socket createSocket(InetAddress host, int port)
250
+ throws IOException
251
+ {
252
+ Socket sock = next.createSocket(host, port);
253
+ setSSLParameters(sock, true);
254
+ return sock;
255
+ }
256
+
257
+ @Override
258
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
259
+ throws IOException
260
+ {
261
+ Socket sock = next.createSocket(address, port, localAddress, localPort);
262
+ setSSLParameters(sock, true);
263
+ return sock;
264
+ }
265
+
266
+ private void setSSLParameters(Socket sock, boolean setHostname)
267
+ {
268
+ if (sock instanceof SSLSocket) {
269
+ SSLSocket s = (SSLSocket) sock;
270
+ String identAlgorithm = s.getSSLParameters().getEndpointIdentificationAlgorithm();
271
+ if (identAlgorithm != null && identAlgorithm.equalsIgnoreCase("HTTPS")) {
272
+ // hostname verification is already configured.
273
+ } else {
274
+ if (setHostname && s instanceof SSLSocketImpl) {
275
+ ((SSLSocketImpl) s).setHost(hostname);
276
+ }
277
+ SSLParameters params = s.getSSLParameters();
278
+ params.setEndpointIdentificationAlgorithm("HTTPS");
279
+ s.setSSLParameters(params);
280
+ // s.startHandshake
281
+ }
282
+ }
283
+ }
284
+ }
285
+ }
@@ -0,0 +1,5 @@
1
+ package org.embulk.output.ftp;
2
+
3
+ public class TestBlockingTransfer
4
+ {
5
+ }
@@ -0,0 +1,5 @@
1
+ package org.embulk.output.ftp;
2
+
3
+ public class TestFtpFileOutputPlugin
4
+ {
5
+ }
@@ -0,0 +1,5 @@
1
+ package org.embulk.output.ftp;
2
+
3
+ public class TestSSLPlugins
4
+ {
5
+ }
@@ -0,0 +1,5 @@
1
+ package org.embulk.output.ftp;
2
+
3
+ public class TrustedManagers
4
+ {
5
+ }
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: embulk-output-ftp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Satoshi Akama
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ~>
17
+ - !ruby/object:Gem::Version
18
+ version: '1.0'
19
+ name: bundler
20
+ prerelease: false
21
+ type: :development
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '10.0'
33
+ name: rake
34
+ prerelease: false
35
+ type: :development
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Stores files on FTP.
42
+ email:
43
+ - satoshiakama@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - .travis.yml
50
+ - CHANGELOG.md
51
+ - README.md
52
+ - build.gradle
53
+ - config/checkstyle/checkstyle.xml
54
+ - config/checkstyle/default.xml
55
+ - embulk-output-ftp.gemspec
56
+ - gradle/wrapper/gradle-wrapper.jar
57
+ - gradle/wrapper/gradle-wrapper.properties
58
+ - gradlew
59
+ - gradlew.bat
60
+ - lib/embulk/output/ftp.rb
61
+ - libs/ftp4j-1.7.2.jar
62
+ - src/main/java/org/embulk/output/ftp/BlockingTransfer.java
63
+ - src/main/java/org/embulk/output/ftp/FtpFileOutputPlugin.java
64
+ - src/main/java/org/embulk/output/ftp/SSLPlugins.java
65
+ - src/main/java/org/embulk/output/ftp/TrustManagers.java
66
+ - src/test/java/org/embulk/output/ftp/TestBlockingTransfer.java
67
+ - src/test/java/org/embulk/output/ftp/TestFtpFileOutputPlugin.java
68
+ - src/test/java/org/embulk/output/ftp/TestSSLPlugins.java
69
+ - src/test/java/org/embulk/output/ftp/TrustedManagers.java
70
+ - classpath/bcpkix-jdk15on-1.52.jar
71
+ - classpath/bcprov-jdk15on-1.52.jar
72
+ - classpath/embulk-output-ftp-0.1.0.jar
73
+ - classpath/ftp4j-1.7.2.jar
74
+ homepage: https://github.com/sakama/embulk-output-ftp
75
+ licenses:
76
+ - Apache 2.0
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.1.9
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: FTP file output plugin for Embulk
98
+ test_files: []