Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept private key for TLS server without passphrase #1575

Merged
merged 1 commit into from
May 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/fluent/plugin_helper/cert_option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ def cert_option_server_validate!(conf)
case
when conf.cert_path
raise Fluent::ConfigError, "private_key_path is required when cert_path is specified" unless conf.private_key_path
raise Fluent::ConfigError, "private_key_passphrase is required when cert_path is specified" unless conf.private_key_passphrase
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about logging warn message like "For security reason, setting private_key_passphrase is recommended"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough.

log.warn "For security reason, setting private_key_passphrase is recommended when cert_path is specified" unless conf.private_key_passphrase
cert_option_load(conf.cert_path, conf.private_key_path, conf.private_key_passphrase)

when conf.ca_cert_path
raise Fluent::ConfigError, "ca_private_key_path is required when ca_cert_path is specified" unless conf.ca_private_key_path
raise Fluent::ConfigError, "ca_private_key_passphrase is required when ca_cert_path is specified" unless conf.ca_private_key_passphrase
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

log.warn "For security reason, setting ca_private_key_passphrase is recommended when ca_cert_path is specified" unless conf.ca_private_key_passphrase
generate_opts = cert_option_cert_generation_opts_from_conf(conf)
cert_option_generate_server_pair_by_ca(
conf.ca_cert_path,
Expand Down
68 changes: 37 additions & 31 deletions test/plugin_helper/test_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -767,8 +767,9 @@ def create_server_options

def write_cert_and_key(cert_path, cert, key_path, key, passphrase)
File.open(cert_path, "w"){|f| f.write(cert.to_pem) }
# Encrypt secret key by AES256, and write it in PEM format
File.open(key_path, "w"){|f| f.write(key.export(OpenSSL::Cipher.new("AES-256-CBC"), passphrase)) }
# Write the secret key (raw or ecnrypted by AES256) in PEM format
key_str = passphrase ? key.export(OpenSSL::Cipher.new("AES-256-CBC"), passphrase) : key.export
File.open(key_path, "w"){|f| f.write(key_str) }
File.chmod(0600, cert_path, key_path)
end

Expand Down Expand Up @@ -807,7 +808,8 @@ def create_server_pair_chained_with_root_ca(ca_cert_path, ca_key_path, ca_key_pa
f.write server_cert.to_pem
f.write chain_cert.to_pem
end
File.open(private_key_path, "w"){|f| f.write(server_key.export(OpenSSL::Cipher.new("AES-256-CBC"), passphrase)) }
key_str = passphrase ? server_key.export(OpenSSL::Cipher.new("AES-256-CBC"), passphrase) : server_key.export
File.open(private_key_path, "w"){|f| f.write(key_str) }
File.chmod(0600, cert_path, private_key_path)
end

Expand Down Expand Up @@ -889,10 +891,11 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
assert_equal "yay\nfoo\n", received
end

test 'load self-signed cert/key pair (files), verified from clients using cert files' do
data('with passphrase' => 'yaaaaaaaaaaaaaaaaaaay',
'without passphrase' => nil)
test 'load self-signed cert/key pair (files), verified from clients using cert files' do |private_key_passphrase|
cert_path = File.join(@server_cert_dir, "cert.pem")
private_key_path = File.join(@certs_dir, "server.key.pem")
private_key_passphrase = "yaaaaaaaaaaaaaaaaaaay"
create_server_pair_signed_by_self(cert_path, private_key_path, private_key_passphrase)

tls_options = {
Expand All @@ -902,8 +905,8 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
insecure: false,
cert_path: cert_path,
private_key_path: private_key_path,
private_key_passphrase: private_key_passphrase,
}
tls_options[:private_key_passphrase] = private_key_passphrase if private_key_passphrase
received = ""
@d.server_create_tls(:s, PORT, tls_options: tls_options) do |data, conn|
received << data
Expand All @@ -922,10 +925,11 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
assert_equal "yay\nfoo\n", received
end

test 'create dynamic server cert by private CA cert file, verified from clients using CA cert file' do
data('with passphrase' => "fooooooooooooooooooooooooo",
'without passphrase' => nil)
test 'create dynamic server cert by private CA cert file, verified from clients using CA cert file' do |ca_key_passphrase|
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
ca_key_path = File.join(@certs_dir, "ca.key.pem")
ca_key_passphrase = "fooooooooooooooooooooooooo"
create_ca_pair_signed_by_self(ca_cert_path, ca_key_path, ca_key_passphrase)

tls_options = {
Expand All @@ -935,9 +939,9 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
insecure: false,
ca_cert_path: ca_cert_path,
ca_private_key_path: ca_key_path,
ca_private_key_passphrase: ca_key_passphrase,
generate_private_key_length: 2048,
}
tls_options[:ca_private_key_passphrase] = ca_key_passphrase if ca_key_passphrase
received = ""
@d.server_create_tls(:s, PORT, tls_options: tls_options) do |data, conn|
received << data
Expand All @@ -950,15 +954,15 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
assert_equal "yay\nfoo\n", received
end

test 'load static server cert by private CA cert file, verified from clients using CA cert file' do
data('with passphrase' => ["foooooooo", "yaaaaaaaaaaaaaaaaaaay"],
'without passphrase' => [nil, nil])
test 'load static server cert by private CA cert file, verified from clients using CA cert file' do |(ca_key_passphrase, private_key_passphrase)|
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
ca_key_path = File.join(@certs_dir, "ca.key.pem")
ca_key_passphrase = "foooooooo"
create_ca_pair_signed_by_self(ca_cert_path, ca_key_path, ca_key_passphrase)

cert_path = File.join(@server_cert_dir, "cert.pem")
private_key_path = File.join(@certs_dir, "server.key.pem")
private_key_passphrase = "yaaaaaaaaaaaaaaaaaaay"
create_server_pair_signed_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)

tls_options = {
Expand All @@ -968,8 +972,8 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
insecure: false,
cert_path: cert_path,
private_key_path: private_key_path,
private_key_passphrase: private_key_passphrase,
}
tls_options[:private_key_passphrase] = private_key_passphrase if private_key_passphrase
received = ""
@d.server_create_tls(:s, PORT, tls_options: tls_options) do |data, conn|
received << data
Expand All @@ -982,13 +986,13 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
assert_equal "yay\nfoo\n", received
end

test 'load chained server cert by private CA cert file, verified from clients using CA cert file as root' do
data('with passphrase' => ["foooooooo", "yaaaaaaaaaaaaaaaaaaay"],
'without passphrase' => [nil, nil])
test 'load chained server cert by private CA cert file, verified from clients using CA cert file as root' do |(ca_key_passphrase, private_key_passphrase)|
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
ca_key_path = File.join(@certs_dir, "ca.key.pem")
ca_key_passphrase = "foooooooo"
cert_path = File.join(@server_cert_dir, "cert.pem")
private_key_path = File.join(@certs_dir, "server.key.pem")
private_key_passphrase = "yaaaaaaaaaaaaaaaaaaay"
create_server_pair_chained_with_root_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)

tls_options = {
Expand All @@ -998,8 +1002,8 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
insecure: false,
cert_path: cert_path,
private_key_path: private_key_path,
private_key_passphrase: private_key_passphrase,
}
tls_options[:private_key_passphrase] = private_key_passphrase if private_key_passphrase
received = ""
@d.server_create_tls(:s, PORT, tls_options: tls_options) do |data, conn|
received << data
Expand Down Expand Up @@ -1042,17 +1046,18 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
assert_equal "yay\nfoo\n", received
end

test 'load self-signed cert/key pair (files), verified from clients using cert files' do
data('with passphrase' => "yaaaaaaaaaaaaaaaaaaay",
'without passphrase' => nil)
test 'load self-signed cert/key pair (files), verified from clients using cert files' do |private_key_passphrase|
cert_path = File.join(@server_cert_dir, "cert.pem")
private_key_path = File.join(@certs_dir, "server.key.pem")
private_key_passphrase = "yaaaaaaaaaaaaaaaaaaay"
create_server_pair_signed_by_self(cert_path, private_key_path, private_key_passphrase)

transport_opts = {
'cert_path' => cert_path,
'private_key_path' => private_key_path,
'private_key_passphrase' => private_key_passphrase,
}
transport_opts['private_key_passphrase'] = private_key_passphrase if private_key_passphrase
transport_conf = config_element('transport', 'tls', transport_opts)
conf = config_element('match', 'tag.*', {}, [transport_conf])

Expand All @@ -1076,17 +1081,18 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
assert_equal "yay\nfoo\n", received
end

test 'create dynamic server cert by private CA cert file, verified from clients using CA cert file' do
data('with passphrase' => "fooooooooooooooooooooooooo",
'without passphrase' => nil)
test 'create dynamic server cert by private CA cert file, verified from clients using CA cert file' do |ca_key_passphrase|
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
ca_key_path = File.join(@certs_dir, "ca.key.pem")
ca_key_passphrase = "fooooooooooooooooooooooooo"
create_ca_pair_signed_by_self(ca_cert_path, ca_key_path, ca_key_passphrase)

transport_opts = {
'ca_cert_path' => ca_cert_path,
'ca_private_key_path' => ca_key_path,
'ca_private_key_passphrase' => ca_key_passphrase,
}
transport_opts['ca_private_key_passphrase'] = ca_key_passphrase if ca_key_passphrase
transport_conf = config_element('transport', 'tls', transport_opts)
conf = config_element('match', 'tag.*', {}, [transport_conf])

Expand All @@ -1104,22 +1110,22 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
assert_equal "yay\nfoo\n", received
end

test 'load static server cert by private CA cert file, verified from clients using CA cert file' do
data('with passphrase' => ["foooooooo", "yaaaaaaaaaaaaaaaaaaay"],
'without passphrase' => [nil, nil])
test 'load static server cert by private CA cert file, verified from clients using CA cert file' do |(ca_key_passphrase, private_key_passphrase)|
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
ca_key_path = File.join(@certs_dir, "ca.key.pem")
ca_key_passphrase = "foooooooo"
create_ca_pair_signed_by_self(ca_cert_path, ca_key_path, ca_key_passphrase)

cert_path = File.join(@server_cert_dir, "cert.pem")
private_key_path = File.join(@certs_dir, "server.key.pem")
private_key_passphrase = "yaaaaaaaaaaaaaaaaaaay"
create_server_pair_signed_by_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)

transport_opts = {
'cert_path' => cert_path,
'private_key_path' => private_key_path,
'private_key_passphrase' => private_key_passphrase,
}
transport_opts['private_key_passphrase'] = private_key_passphrase if private_key_passphrase
transport_conf = config_element('transport', 'tls', transport_opts)
conf = config_element('match', 'tag.*', {}, [transport_conf])

Expand All @@ -1137,20 +1143,20 @@ def open_tls_session(addr, port, verify: true, cert_path: nil, selfsigned: true,
assert_equal "yay\nfoo\n", received
end

test 'load chained server cert by private CA cert file, verified from clients using CA cert file as root' do
data('with passphrase' => ["foooooooo", "yaaaaaaaaaaaaaaaaaaay"],
'without passphrase' => [nil, nil])
test 'load chained server cert by private CA cert file, verified from clients using CA cert file as root' do |(ca_key_passphrase, private_key_passphrase)|
ca_cert_path = File.join(@certs_dir, "ca_cert.pem")
ca_key_path = File.join(@certs_dir, "ca.key.pem")
ca_key_passphrase = "foooooooo"
cert_path = File.join(@server_cert_dir, "cert.pem")
private_key_path = File.join(@certs_dir, "server.key.pem")
private_key_passphrase = "yaaaaaaaaaaaaaaaaaaay"
create_server_pair_chained_with_root_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, private_key_passphrase)

transport_opts = {
'cert_path' => cert_path,
'private_key_path' => private_key_path,
'private_key_passphrase' => private_key_passphrase,
}
transport_opts['private_key_passphrase'] = private_key_passphrase if private_key_passphrase
transport_conf = config_element('transport', 'tls', transport_opts)
conf = config_element('match', 'tag.*', {}, [transport_conf])

Expand Down