Skip to content

Commit

Permalink
Adding experimental, optional auto-ssl integration.
Browse files Browse the repository at this point in the history
  • Loading branch information
GUI committed Jun 21, 2018
1 parent 88477cc commit 2f6c5b5
Show file tree
Hide file tree
Showing 20 changed files with 289 additions and 12 deletions.
6 changes: 6 additions & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ globals = {

max_line_length = false

files["src/api-umbrella/auto-ssl"] = {
globals = {
"auto_ssl",
},
}

files["templates/etc/trafficserver"] = {
std = "luajit",
globals = {
Expand Down
14 changes: 14 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,19 @@ tasks:
- ./build/work/stamp/app-deps/lua/penlight
method: checksum

app-deps:lua:resty-auto-ssl:
deps:
- deps:luarocks
cmds:
- ./tasks/app-deps/lua/resty-auto-ssl
sources:
- ./build/work/stamp/deps/luarocks
- ./tasks/app-deps/lua/resty-auto-ssl
- ./tasks/helpers.sh
generates:
- ./build/work/stamp/app-deps/lua/resty-auto-ssl
method: checksum

app-deps:lua:resty-http:
deps:
- deps:luarocks
Expand Down Expand Up @@ -508,6 +521,7 @@ tasks:
- task: app-deps:lua:lustache
- task: app-deps:lua:lyaml
- task: app-deps:lua:penlight
- task: app-deps:lua:resty-auto-ssl
- task: app-deps:lua:resty-http
- task: app-deps:lua:resty-logger-socket
- task: app-deps:lua:resty-shcache
Expand Down
18 changes: 16 additions & 2 deletions build/package/scripts/after-install
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ esac
if [ "$configure" = "true" ]; then
user=api-umbrella
group=api-umbrella
auto_ssl_user=api-umbrella-auto-ssl
auto_ssl_group=api-umbrella-auto-ssl
deploy_user=api-umbrella-deploy
deploy_group=api-umbrella-deploy
destdir="${DESTDIR:-}"
Expand All @@ -51,6 +53,15 @@ if [ "$configure" = "true" ]; then
-d "$prefix_dir" -c "API Umbrella user" "$user"
fi

# Create the auto-ssl user & group.
if ! getent group "$auto_ssl_group" > /dev/null; then
groupadd -r "$auto_ssl_group"
fi
if ! getent passwd "$auto_ssl_user" > /dev/null; then
useradd -r -g "$auto_ssl_group" -s /bin/nologin \
-d "$prefix_dir" -c "API Umbrella auto-ssl user" "$auto_ssl_user"
fi

# Create the deploy user & group.
if ! getent group "$deploy_group" > /dev/null; then
groupadd -r "$deploy_group"
Expand All @@ -60,8 +71,11 @@ if [ "$configure" = "true" ]; then
-d "$destdir/home/$deploy_user" -c "API Umbrella deployment user" "$deploy_user"
fi

# Add the deploy user to the app group, so the deploy user can read config
# files.
# Add the auto-ssl and deploy users to the app group, so these users can read
# config files.
if ! groups "$auto_ssl_user" | grep -q -E "\\s$group(\\s|$)"; then
usermod -a -G "$group" "$auto_ssl_user"
fi
if ! groups "$deploy_user" | grep -q -E "\\s$group(\\s|$)"; then
usermod -a -G "$group" "$deploy_user"
fi
Expand Down
11 changes: 11 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,17 @@ router:
web_app_host: "*"
website_backend_required_https_regex_default: "^.*"
redirect_not_found_to_https: true
auto_ssl:
workers: 1
worker_connections: 8192
http:
port: 14005
https:
port: 14006
user: api-umbrella-auto-ssl
group: api-umbrella-auto-ssl
hook_server:
port: 14007
rsyslog:
host: 127.0.0.1
port: 14014
Expand Down
7 changes: 7 additions & 0 deletions src/api-umbrella/auto-ssl/hooks/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
config = require "api-umbrella.proxy.models.file_config"

auto_ssl = (require "resty.auto-ssl").new({
hook_server_port = config["auto_ssl"]["hook_server"]["port"]
})

auto_ssl:init()
1 change: 1 addition & 0 deletions src/api-umbrella/auto-ssl/hooks/init_worker.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
auto_ssl:init_worker()
1 change: 1 addition & 0 deletions src/api-umbrella/auto-ssl/hooks/ssl_certificate.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
auto_ssl:ssl_certificate()
1 change: 1 addition & 0 deletions src/api-umbrella/cli/read_config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ local function set_computed_config()
["_service_log_db_enabled?"] = array_includes(config["services"], "log_db"),
["_service_elasticsearch_aws_signing_proxy_enabled?"] = array_includes(config["services"], "elasticsearch_aws_signing_proxy"),
["_service_router_enabled?"] = array_includes(config["services"], "router"),
["_service_auto_ssl_enabled?"] = array_includes(config["services"], "auto_ssl"),
["_service_web_enabled?"] = array_includes(config["services"], "web"),
["_service_nginx_reloader_enabled?"] = (array_includes(config["services"], "router") and config["nginx"]["_reloader_frequency"]),
router = {
Expand Down
45 changes: 35 additions & 10 deletions src/api-umbrella/cli/setup.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ local function prepare()
end
end

local function generate_cert(subject, key_filename, crt_filename)
local ssl_dir = path.join(config["etc_dir"], "ssl");
local ssl_key_path = path.join(ssl_dir, key_filename);
local ssl_crt_path = path.join(ssl_dir, crt_filename);

if not path.exists(ssl_key_path) or not path.exists(ssl_crt_path) then
dir.makepath(ssl_dir)
local _, _, err = run_command({ "openssl", "req", "-new", "-newkey", "rsa:2048", "-days", "3650", "-nodes", "-x509", "-subj", subject, "-keyout", ssl_key_path, "-out", ssl_crt_path })
if err then
print(err)
os.exit(1)
end
end
end

local function generate_self_signed_cert()
local cert_required = false
if config["hosts"] then
Expand All @@ -90,21 +105,27 @@ local function generate_self_signed_cert()
end

if cert_required then
local ssl_dir = path.join(config["etc_dir"], "ssl");
local ssl_key_path = path.join(ssl_dir, "self_signed.key");
local ssl_crt_path = path.join(ssl_dir, "self_signed.crt");

if not path.exists(ssl_key_path) or not path.exists(ssl_crt_path) then
dir.makepath(ssl_dir)
local _, _, err = run_command({ "openssl", "req", "-new", "-newkey", "rsa:2048", "-days", "3650", "-nodes", "-x509", "-subj", "/O=API Umbrella/CN=apiumbrella.example.com", "-keyout", ssl_key_path, "-out", ssl_crt_path })
if err then
print(err)
os.exit(1)
generate_cert("/O=API Umbrella/CN=apiumbrella.example.com", "self_signed.key", "self_signed.crt")
end
end

local function generate_auto_ssl_fallback_cert()
local cert_required = false
if config["hosts"] then
for _, host in ipairs(config["hosts"]) do
if not host["ssl_cert"] then
cert_required = true
break
end
end
end

if cert_required then
generate_cert("/CN=sni-support-required-for-valid-ssl", "auto_ssl_fallback.key", "auto_ssl_fallback.crt")
end
end


local function ensure_geoip_db()
-- If the city db path doesn't exist, copy it from the package installation
-- location to the runtime location (this path will then be overwritten by
Expand Down Expand Up @@ -250,6 +271,9 @@ local function activate_services()
active_services["rsyslog"] = 1
active_services["trafficserver"] = 1
end
if config["_service_auto_ssl_enabled?"] then
active_services["nginx-auto-ssl"] = 1
end
if config["_service_web_enabled?"] then
active_services["web-delayed-job"] = 1
active_services["web-puma"] = 1
Expand Down Expand Up @@ -339,6 +363,7 @@ return function()
permission_check()
prepare()
generate_self_signed_cert()
generate_auto_ssl_fallback_cert()
ensure_geoip_db()
write_templates()
write_static_site_key()
Expand Down
10 changes: 10 additions & 0 deletions tasks/app-deps/lua/resty-auto-ssl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

lua_resty_auto_ssl_version="0.12.0-1"

set -e -u -x
source ./tasks/helpers.sh

luarocks_install "lua-resty-auto-ssl" "$lua_resty_auto_ssl_version"

stamp
6 changes: 6 additions & 0 deletions templates/etc/nginx/auto-ssl-cert.conf.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Dynamic handler for issuing or returning certs.
ssl_certificate_by_lua_file "{{_src_root_dir}}/src/api-umbrella/auto-ssl/hooks/ssl_certificate.lua";

# Fallback certificate (must be present for nginx to start).
ssl_certificate {{etc_dir}}/ssl/auto_ssl_fallback.crt;
ssl_certificate_key {{etc_dir}}/ssl/auto_ssl_fallback.key;
7 changes: 7 additions & 0 deletions templates/etc/nginx/auto-ssl-proxy-http.conf.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Forwarded-Port 80;

location / {
proxy_pass http://api_umbrella_backend;
}
7 changes: 7 additions & 0 deletions templates/etc/nginx/auto-ssl-proxy-https.conf.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;

location / {
proxy_pass http://api_umbrella_backend;
}
9 changes: 9 additions & 0 deletions templates/etc/nginx/auto-ssl-proxy.conf.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
server_name _;

proxy_buffering off;
proxy_connect_timeout {{nginx._initial_proxy_connect_timeout}}s;
proxy_read_timeout {{nginx._initial_proxy_read_timeout}}s;
proxy_send_timeout {{nginx._initial_proxy_send_timeout}}s;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
136 changes: 136 additions & 0 deletions templates/etc/nginx/auto-ssl.conf.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
worker_processes {{auto_ssl.workers}};

daemon off;

{{#auto_ssl.user}}
user {{auto_ssl.user}} {{auto_ssl.group}};
{{/auto_ssl.user}}
{{^auto_ssl.user}}
{{#_effective_user_name}}
# Even if user switching isn't enabled, make sure nginx uses the current
# effective user and group for launching the child workers (so nginx's default
# usage of the "nobody" user isn't used).
user {{_effective_user_name}} {{_effective_group_name}};
{{/_effective_user_name}}
{{/auto_ssl.user}}

pid {{run_dir}}/nginx-auto-ssl.pid;

events {
worker_connections {{auto_ssl.worker_connections}};
}

error_log stderr;

pcre_jit on;

http {
access_log {{log_dir}}/nginx-auto-ssl/{{nginx.access_log_filename}} combined {{nginx.access_log_options}};

client_body_temp_path {{tmp_dir}}/nginx-auto-ssl-client_body_temp;
proxy_temp_path {{tmp_dir}}/nginx-auto-ssl-proxy_temp;
fastcgi_temp_path {{tmp_dir}}/nginx-auto-ssl-fastcgi_temp;
uwsgi_temp_path {{tmp_dir}}/nginx-auto-ssl-uwsgi_temp;
scgi_temp_path {{tmp_dir}}/nginx-auto-ssl-scgi_temp;
server_tokens off;

lua_package_path '{{_package_path}}';
lua_package_cpath '{{_package_cpath}}';

# Quiet the raw socket errors from the logs, since we should be handling any
# connection errors as appropriate in the Lua code.
lua_socket_log_errors off;

# The "auto_ssl" shared dict must be defined with enough storage space to
# hold your certificate data.
lua_shared_dict auto_ssl 5m;

# The "auto_ssl" shared dict is used to temporarily store various settings
# like the secret used by the hook server. Do not change or omit it.
lua_shared_dict auto_ssl_settings 64k;

{{#dns_resolver._nameservers_nginx}}
resolver {{dns_resolver._nameservers_nginx}};
resolver_timeout 12s;
{{/dns_resolver._nameservers_nginx}}

init_by_lua_file "{{_src_root_dir}}/src/api-umbrella/auto-ssl/hooks/init.lua";
init_worker_by_lua_file "{{_src_root_dir}}/src/api-umbrella/auto-ssl/hooks/init.lua";

lua_check_client_abort on;
if_modified_since off;

include ./mime.conf;
include ./realip.conf;

# Allow any sized uploads to backends.
client_max_body_size 0;

keepalive_timeout {{nginx.keepalive_timeout}}s;

ssl_protocols {{nginx.ssl_protocols}};
ssl_ciphers {{nginx.ssl_ciphers}};
ssl_session_cache {{nginx.ssl_session_cache}};
ssl_session_timeout {{nginx.ssl_session_timeout}};
ssl_session_tickets {{nginx.ssl_session_tickets}};
ssl_buffer_size {{nginx.ssl_buffer_size}};
ssl_prefer_server_ciphers {{nginx.ssl_prefer_server_ciphers}};
ssl_ecdh_curve {{nginx.ssl_ecdh_curve}};

{{#nginx.dhparam}}
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam {{nginx.dhparam}};
{{/nginx.dhparam}}

{{#nginx.server_names_hash_bucket_size}}
server_names_hash_bucket_size {{nginx.server_names_hash_bucket_size}};
{{/nginx.server_names_hash_bucket_size}}

upstream api_umbrella_backend {
server 127.0.0.1:{{http_port}};
keepalive 10;
}

server {
{{#listen.addresses}}
listen {{.}}:{{auto_ssl.https.port}} ssl default_server so_keepalive=on;
{{/listen.addresses}}

include ./auto-ssl-cert.conf;
include ./auto-ssl-proxy.conf;
include ./auto-ssl-proxy-https.conf;
}

# HTTP server
server {
{{#listen.addresses}}
listen {{.}}:{{auto_ssl.http.port}} default_server so_keepalive=on;
{{/listen.addresses}}

# Endpoint used for performing domain verification with Let's Encrypt.
location /.well-known/acme-challenge/ {
content_by_lua_block {
auto_ssl:challenge_server()
}
}

include ./auto-ssl-proxy.conf;
include ./auto-ssl-proxy-http.conf;
}

# Internal server for handling certificate tasks.
server {
listen 127.0.0.1:{{auto_ssl.hook_server.port}} so_keepalive=on;

# Increase the body buffer size, to ensure the internal POSTs can always
# parse the full POST contents into memory.
client_body_buffer_size 128k;
client_max_body_size 128k;

location / {
content_by_lua_block {
auto_ssl:hook_server()
}
}
}
}
1 change: 1 addition & 0 deletions templates/etc/nginx/log_format.conf.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions templates/etc/nginx/router.conf.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ http {
rewrite {{.}};
{{/rewrites}}

# Optional host-specific realip settings.
{{#set_real_ip_from}}
set_real_ip_from {{.}};
{{/set_real_ip_from}}
Expand Down
1 change: 1 addition & 0 deletions templates/etc/perp/nginx-auto-ssl/rc.env.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
API_UMBRELLA_RUNTIME_CONFIG={{_api_umbrella_config_runtime_file}}
3 changes: 3 additions & 0 deletions templates/etc/perp/nginx-auto-ssl/rc.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
set -e -u
exec ../rc.log "$@"

0 comments on commit 2f6c5b5

Please sign in to comment.