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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/README.md +25 -0
- data/Rakefile +10 -0
- data/fluent-plugin-aes-forward.gemspec +24 -0
- data/lib/fluent/plugin/in_aes_forward.rb +56 -0
- data/lib/fluent/plugin/out_aes_forward.rb +63 -0
- data/test/helper.rb +21 -0
- data/test/test_in_aes_forward.rb +133 -0
- data/test/test_out_aes_forward.rb +45 -0
- metadata +99 -0
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
data/Gemfile
ADDED
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,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
|