embulk-output-ftp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []