Skip to content
This repository has been archived by the owner on Dec 31, 2022. It is now read-only.

Commit

Permalink
Added DHparams and nginx version detection support. Resolves #8 and r…
Browse files Browse the repository at this point in the history
…esolves #9
  • Loading branch information
Igor Rzegocki committed Apr 17, 2016
1 parent a782a64 commit 4e60594
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 4 deletions.
1 change: 1 addition & 0 deletions attributes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
## common

default['defaults']['webserver']['adapter'] = 'nginx'
default['defaults']['webserver']['ssl_for_legacy_browsers'] = false

## nginx

Expand Down
20 changes: 17 additions & 3 deletions libraries/drivers_webserver_nginx.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ class Nginx < Drivers::Webserver::Base
adapter :nginx
allowed_engines :nginx
output filter: [
:build_type, :client_body_timeout, :client_header_timeout, :client_max_body_size, :keepalive_timeout,
:log_dir, :proxy_read_timeout, :proxy_send_timeout, :send_timeout
:build_type, :client_body_timeout, :client_header_timeout, :client_max_body_size, :dhparams, :keepalive_timeout,
:log_dir, :proxy_read_timeout, :proxy_send_timeout, :send_timeout, :ssl_for_legacy_browsers
]
# notifies action: :restart,
# resource: proc { |app| "service[nginx_#{app['shortname']}]" },
Expand All @@ -21,6 +21,7 @@ def configure(context)
add_ssl_item(context, :private_key)
add_ssl_item(context, :certificate)
add_ssl_item(context, :chain)
add_dhparams(context)

add_unicorn_config(context) if Drivers::Appserver::Factory.build(app, node).adapter == 'unicorn'
enable_appserver_config(context)
Expand All @@ -44,12 +45,25 @@ def add_ssl_item(context, name)
context.template "/etc/nginx/ssl/#{app[:domains].first}.#{extensions[name]}" do
owner 'root'
group 'root'
mode '0644'
mode name == :private_key ? '0600' : '0644'
source 'ssl_key.erb'
variables key_data: key_data
end
end

def add_dhparams(context)
dhparams = out[:dhparams]
return if dhparams.blank?

context.template "/etc/nginx/ssl/#{app[:domains].first}.dhparams.pem" do
owner 'root'
group 'root'
mode '0600'
source 'ssl_key.erb'
variables key_data: dhparams
end
end

def add_unicorn_config(context)
deploy_to = deploy_dir(app)
application = app
Expand Down
6 changes: 5 additions & 1 deletion spec/fixtures/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ def node(override = {})
lsb: {
codename: 'trusty'
},
nginx: {
version: '1.4.6'
},
deploy: {
dummy_project: {
database: {
Expand Down Expand Up @@ -33,7 +36,8 @@ def node(override = {})
},
webserver: {
adapter: 'nginx',
client_max_body_size: '125m'
client_max_body_size: '125m',
dhparams: '--- DH PARAMS ---'
},
framework: {
adapter: 'rails',
Expand Down
1 change: 1 addition & 0 deletions spec/unit/libraries/drivers_webserver_nginx_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
it 'returns proper out data' do
expect(described_class.new(aws_opsworks_app, node).out).to eq(
client_max_body_size: '125m',
dhparams: '--- DH PARAMS ---',
keepalive_timeout: '15'
)
end
Expand Down
39 changes: 39 additions & 0 deletions spec/unit/recipes/configure_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
let(:chef_run) do
ChefSpec::SoloRunner.new do |solo_node|
solo_node.set['deploy'] = node['deploy']
solo_node.set['nginx'] = node['nginx']
end.converge(described_recipe)
end
before do
Expand Down Expand Up @@ -100,9 +101,44 @@
expect(chef_run)
.to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}")
.with_content('ssl_certificate_key /etc/nginx/ssl/dummy-project.example.com.key;')
expect(chef_run)
.to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}")
.with_content('ssl_dhparam /etc/nginx/ssl/dummy-project.example.com.dhparams.pem;')
expect(chef_run)
.to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}")
.with_content('ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";')
expect(chef_run)
.to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}")
.with_content('ssl_ecdh_curve secp384r1;')
expect(chef_run)
.to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}")
.with_content('ssl_stapling on;')
expect(chef_run)
.not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}")
.with_content('ssl_session_tickets off;')
expect(chef_run).to create_link("/etc/nginx/sites-enabled/#{aws_opsworks_app['shortname']}")
end

it 'enables ssl rules for legacy browsers in nginx config' do
chef_run = ChefSpec::SoloRunner.new do |solo_node|
deploy = node['deploy']
deploy[aws_opsworks_app['shortname']]['webserver']['ssl_for_legacy_browsers'] = true
solo_node.set['deploy'] = deploy
solo_node.set['nginx'] = node['nginx']
end.converge(described_recipe)
expect(chef_run).to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}").with_content(
'ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES128-GCM-SHA384:' \
'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA128:DHE-RSA-AES128-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:' \
'DHE-RSA-AES128-GCM-SHA128:ECDHE-RSA-AES128-SHA384:ECDHE-RSA-AES128-SHA128:ECDHE-RSA-AES128-SHA:' \
'ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:' \
'ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA384:AES128-GCM-SHA128:AES128-SHA128:AES128-SHA128:' \
'AES128-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";'
)
expect(chef_run)
.not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}")
.with_content('ssl_ecdh_curve secp384r1;')
end

it 'creates SSL keys for nginx' do
expect(chef_run).to create_directory('/etc/nginx/ssl')
expect(chef_run)
Expand All @@ -114,6 +150,9 @@
expect(chef_run)
.to render_file("/etc/nginx/ssl/#{aws_opsworks_app['domains'].first}.ca")
.with_content('--- SSL CERTIFICATE CHAIN ---')
expect(chef_run)
.to render_file("/etc/nginx/ssl/#{aws_opsworks_app['domains'].first}.dhparams.pem")
.with_content('--- DH PARAMS ---')
end
end
end
23 changes: 23 additions & 0 deletions templates/default/unicorn.nginx.conf.erb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,29 @@ server {
ssl_client_certificate /etc/nginx/ssl/<%= @application[:domains].first %>.ca;
<% end -%>

<% if @out[:ssl_for_legacy_browsers] -%>
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES128-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA128:DHE-RSA-AES128-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA128:ECDHE-RSA-AES128-SHA384:ECDHE-RSA-AES128-SHA128:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA384:AES128-GCM-SHA128:AES128-SHA128:AES128-SHA128:AES128-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
<% else -%>
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
<% if Gem::Version.new(node['nginx']['version']) >= Gem::Version.new('1.1.0') -%>
ssl_ecdh_curve secp384r1;
<% end -%>
<% end -%>

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
<% if Gem::Version.new(node['nginx']['version']) >= Gem::Version.new('1.5.9') -%>
ssl_session_tickets off;
<% end -%>
<% if Gem::Version.new(node['nginx']['version']) >= Gem::Version.new('1.3.7') -%>
ssl_stapling on;
ssl_stapling_verify on;
<% end -%>
<% if @out[:dhparams].present? -%>
ssl_dhparam /etc/nginx/ssl/<%= @application[:domains].first %>.dhparams.pem;
<% end -%>

root <%= File.join(@deploy_dir, 'public') %>;

client_max_body_size <%= @out[:client_max_body_size] || '1m' %>;
Expand Down

0 comments on commit 4e60594

Please sign in to comment.