fluent-plugin-aes-forward 0.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2638e8e8e4b855dcf519924f0637a3f17c00ad8d
4
+ data.tar.gz: e0dff996a87812b92ff3b595214faac78b5f12aa
5
+ SHA512:
6
+ metadata.gz: bf97f4d5981e9e231d209bddd225f48be6688da2b9a04e77211866780e1d01805e90d4281dcdb686e4f631c8a60a436feff29b51c2f0eee7d1aef72a464c14d6
7
+ data.tar.gz: a2e92c6cbe1d8b48e4420e15280d9a8ec170c0d3ae019812d7f263be36a053b68d31590e11a67176c9e12ad7418f378c96bdc512a236da1a1b7968cc7139a398
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-aes-forward.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # Fluent AES forward plugin
2
+
3
+ - This plugin is encrypt data at AES while transfer data.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'fluent-plugin-aes-forward'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install fluent-plugin-aes-forward
18
+
19
+ # License
20
+
21
+ [Apache License Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
22
+
23
+ # Copyright
24
+
25
+ Copyright (c) 2013 Aiming Inc.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << "lib" << "test"
6
+ test.pattern = "test/**/test_*.rb"
7
+ test.verbose = true
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-plugin-aes-forward"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["futoase"]
9
+ spec.email = ["futoase@gmail.com"]
10
+ spec.description = %q{fluent plugin aes forward}
11
+ spec.summary = %q{This plugin is encrypt data at AES while transfer data.}
12
+ spec.homepage = "https://github.com/aiming/fluent-plugin-aes-forward"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "rake"
22
+
23
+ spec.add_dependency "fluentd"
24
+ end
@@ -0,0 +1,56 @@
1
+ require "fluent/plugin/in_forward"
2
+ require "openssl"
3
+ require "base64"
4
+
5
+ module Fluent
6
+ class AESForwardInput < ForwardInput
7
+ Fluent::Plugin.register_input('aes_forward', self)
8
+
9
+ config_param :key, :string, default: ""
10
+ config_param :iv, :string, default: ""
11
+
12
+ def decrypt_data(record)
13
+ decipher = OpenSSL::Cipher::AES.new(256, :CBC).decrypt
14
+ decipher.key = @key
15
+ decipher.iv = @iv
16
+ decipher.update(Base64.decode64(record)) + decipher.final
17
+ end
18
+
19
+ def on_message(msg)
20
+ if msg.nil?
21
+ # for future TCP heartbeat_request
22
+ return
23
+ end
24
+
25
+ # TODO format error
26
+ tag = msg[0].to_s
27
+ entries = decrypt_data(msg[1])
28
+
29
+ if entries.class == String
30
+ # PackedForward
31
+ es = MessagePackEventStream.new(entries, @cached_unpacker)
32
+ Engine.emit_stream(tag, es)
33
+
34
+ elsif entries.class == Array
35
+ # Forward
36
+ es = MultiEventStream.new
37
+ entries.each {|e|
38
+ record = e[1]
39
+ next if record.nil?
40
+ time = e[0].to_i
41
+ time = (now ||= Engine.now) if time == 0
42
+ es.add(time, record)
43
+ }
44
+ Engine.emit_stream(tag, es)
45
+
46
+ else
47
+ # Message
48
+ record = msg[2]
49
+ return if record.nil?
50
+ time = msg[1]
51
+ time = Engine.now if time == 0
52
+ Engine.emit(tag, time, record)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,63 @@
1
+ require "fluent/plugin/out_forward"
2
+ require "fluent/plugin/buf_memory"
3
+ require "base64"
4
+ require "openssl"
5
+
6
+ module Fluent
7
+
8
+ MemoryBufferChunk.class_eval do
9
+ def encrypt!(key, iv)
10
+ cipher = OpenSSL::Cipher::AES.new(256, :CBC).encrypt
11
+ cipher.key = key
12
+ cipher.iv = iv
13
+ cipher.encrypt
14
+ @data = Base64.encode64(cipher.update(@data) + cipher.final)
15
+ end
16
+ end
17
+
18
+ class AESForwardOutput < ForwardOutput
19
+ Fluent::Plugin.register_output('aes_forward', self)
20
+
21
+ config_param :key, :string, default: ""
22
+ config_param :iv, :string, default: ""
23
+
24
+ def send_data(node, tag, chunk)
25
+ sock = connect(node)
26
+ begin
27
+ opt = [1, @send_timeout.to_i].pack('I!I!') # { int l_onoff; int l_linger; }
28
+ sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, opt)
29
+
30
+ opt = [@send_timeout.to_i, 0].pack('L!L!') # struct timeval
31
+ sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, opt)
32
+
33
+ # beginArray(2)
34
+ sock.write FORWARD_HEADER
35
+
36
+ # writeRaw(tag)
37
+ sock.write tag.to_msgpack # tag
38
+
39
+ chunk.encrypt!(@key, @iv)
40
+
41
+ # beginRaw(size)
42
+ sz = chunk.size
43
+ #if sz < 32
44
+ # # FixRaw
45
+ # sock.write [0xa0 | sz].pack('C')
46
+ #elsif sz < 65536
47
+ # # raw 16
48
+ # sock.write [0xda, sz].pack('Cn')
49
+ #else
50
+ # raw 32
51
+ sock.write [0xdb, sz].pack('CN')
52
+ #end
53
+
54
+ # writeRawBody(packed_es)
55
+ chunk.write_to(sock)
56
+
57
+ node.heartbeat(false)
58
+ ensure
59
+ sock.close
60
+ end
61
+ end
62
+ end
63
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+
3
+ Bundler.setup(:default, :test)
4
+ Bundler.require(:default, :test)
5
+
6
+ require 'fluent/test'
7
+ require 'test/unit'
8
+
9
+ $:.unshift(File.join(File.dirname(__FILE__), '../lib'))
10
+ $:.unshift(File.dirname(__FILE__))
11
+
12
+ def unused_port
13
+ s = TCPServer.open(0)
14
+ port = s.addr[1]
15
+ s.close
16
+ port
17
+ end
18
+
19
+ require 'base64'
20
+ require 'fluent/plugin/in_aes_forward'
21
+ require 'fluent/plugin/out_aes_forward'
@@ -0,0 +1,133 @@
1
+ require_relative 'helper'
2
+
3
+ class InAESForwardTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ PORT = unused_port
9
+ KEY = "hogehogehogehogehogehogehogehoge"
10
+ IV = "mogemogemogemogemogemogemogemoge"
11
+ CONFIG = %[
12
+ key #{KEY}
13
+ iv #{IV}
14
+ port #{PORT}
15
+ bind 127.0.0.1
16
+ ]
17
+
18
+ def create_driver(conf=CONFIG)
19
+ Fluent::Test::InputTestDriver.new(Fluent::AESForwardInput).configure(conf)
20
+ end
21
+
22
+ def test_configure
23
+ d = create_driver
24
+ assert_equal PORT, d.instance.port
25
+ assert_equal '127.0.0.1', d.instance.bind
26
+ end
27
+
28
+ def connect
29
+ TCPSocket.new('127.0.0.1', PORT)
30
+ end
31
+
32
+ def encrypt_data(data)
33
+ cipher = OpenSSL::Cipher::AES.new(256, :CBC).encrypt
34
+ cipher.key = KEY
35
+ cipher.iv = IV
36
+ Base64.encode64(cipher.update(Marshal.dump(data)) + cipher.final)
37
+ end
38
+
39
+ def test_time
40
+ d = create_driver
41
+
42
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
43
+ Fluent::Engine.now = time
44
+
45
+ d.expect_emit "tag1", time, { "a" => 1 }
46
+ d.expect_emit "tag2", time, { "a" => 2 }
47
+
48
+ d.run do
49
+ d.expected_emits.each do |tag, time, record|
50
+ send_data [tag, 0, record].map { |x| encrypt_data(x) }.to_msgpack
51
+ end
52
+ sleep 0.5
53
+ end
54
+ end
55
+
56
+ def test_message
57
+ d = create_driver
58
+
59
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
60
+
61
+ d.expect_emit "tag1", time, { "a" => 1 }
62
+ d.expect_emit "tag2", time, { "a" => 2 }
63
+
64
+ d.run do
65
+ d.expected_emits.each do |tag, time, record|
66
+ send_data [tag, time, record].map { |x| encrypt_data(x) }.to_msgpack
67
+ end
68
+ sleep 0.5
69
+ end
70
+ end
71
+
72
+ def test_forward
73
+ d = create_driver
74
+
75
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
76
+
77
+ d.expect_emit "tag1", time, { "a" => 1 }
78
+ d.expect_emit "tag1", time, { "a" => 2 }
79
+
80
+ d.run do
81
+ entries = []
82
+ d.expected_emits.each do |tag, time, record|
83
+ entries << [time, record]
84
+ end
85
+ send_data ["tag1", entries].map { |x| encrypt_data(x) }.to_msgpack
86
+ sleep 0.5
87
+ end
88
+ end
89
+
90
+ def test_packed_forward
91
+ d = create_driver
92
+
93
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
94
+
95
+ d.expect_emit "tag1", time, { "a" => 1 }
96
+ d.expect_emit "tag1", time, { "a" => 2 }
97
+
98
+ d.run do
99
+ entries = ''
100
+ d.expected_emits.each do |tag, time, record|
101
+ [time, record].to_msgpack(entries)
102
+ end
103
+ send_data ["tag1", entries].map { |x| encrypt_data(x) }.to_msgpack
104
+ sleep 0.5
105
+ end
106
+ end
107
+
108
+ def test_message_json
109
+ d = create_driver
110
+
111
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
112
+
113
+ d.expect_emit "tag1", time, { "a" => 1 }
114
+ d.expect_emit "tag2", time, { "a" => 2 }
115
+
116
+ d.run do
117
+ d.expected_emits.each do |tag, time, record|
118
+ send_data [tag, time, record].map { |x| encrypt_data(x) }.to_json
119
+ end
120
+ sleep 0.5
121
+ end
122
+ end
123
+
124
+ def send_data(data)
125
+ io = connect
126
+ begin
127
+ io.write data
128
+ ensure
129
+ io.close
130
+ end
131
+ end
132
+
133
+ end
@@ -0,0 +1,45 @@
1
+ require "openssl"
2
+
3
+ class AESForwardOutputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ CONFIG = %[
9
+ send_timeout 51
10
+ key hogehogehogehogehogehogehogehoge
11
+ iv mogemogemogemogemogemogemogemoge
12
+ <server>
13
+ name test
14
+ host 127.0.0.1
15
+ port 13999
16
+ </server>
17
+ ]
18
+
19
+ def create_driver(conf=CONFIG)
20
+ Fluent::Test::OutputTestDriver.new(Fluent::AESForwardOutput) do
21
+ def write(chunk)
22
+ chunk.read
23
+ end
24
+ end.configure(conf)
25
+ end
26
+
27
+ def test_configure
28
+ d = create_driver
29
+ nodes = d.instance.nodes
30
+ assert_equal 51, d.instance.send_timeout
31
+ assert_equal :udp, d.instance.heartbeat_type
32
+ assert_equal 1, nodes.length
33
+ node = nodes.first
34
+ assert_equal "test", node.name
35
+ assert_equal '127.0.0.1', node.host
36
+ assert_equal 13999, node.port
37
+ end
38
+
39
+ def test_configure_tcp_heartbeat
40
+ d = create_driver(CONFIG + "\nheartbeat_type tcp")
41
+ assert_equal :tcp, d.instance.heartbeat_type
42
+ end
43
+
44
+
45
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-aes-forward
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - futoase
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: fluentd
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: fluent plugin aes forward
56
+ email:
57
+ - futoase@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - Gemfile
64
+ - README.md
65
+ - Rakefile
66
+ - fluent-plugin-aes-forward.gemspec
67
+ - lib/fluent/plugin/in_aes_forward.rb
68
+ - lib/fluent/plugin/out_aes_forward.rb
69
+ - test/helper.rb
70
+ - test/test_in_aes_forward.rb
71
+ - test/test_out_aes_forward.rb
72
+ homepage: https://github.com/aiming/fluent-plugin-aes-forward
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.0.3
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: This plugin is encrypt data at AES while transfer data.
96
+ test_files:
97
+ - test/helper.rb
98
+ - test/test_in_aes_forward.rb
99
+ - test/test_out_aes_forward.rb