Skip to content

Change haproxy router to use a certificate list/map file. #11217

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

Merged
merged 1 commit into from
Oct 14, 2016
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
2 changes: 1 addition & 1 deletion images/router/haproxy/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ RUN INSTALL_PKGS="haproxy" && \
yum clean all && \
mkdir -p /var/lib/haproxy/router/{certs,cacerts} && \
mkdir -p /var/lib/haproxy/{conf,run,bin,log} && \
touch /var/lib/haproxy/conf/{{os_http_be,os_edge_http_be,os_tcp_be,os_sni_passthrough,os_reencrypt,os_edge_http_expose,os_edge_http_redirect}.map,haproxy.config} && \
touch /var/lib/haproxy/conf/{{os_http_be,os_edge_http_be,os_tcp_be,os_sni_passthrough,os_reencrypt,os_edge_http_expose,os_edge_http_redirect,cert_config}.map,haproxy.config} && \
chmod -R 777 /var && \
setcap 'cap_net_bind_service=ep' /usr/sbin/haproxy

Expand Down
24 changes: 22 additions & 2 deletions images/router/haproxy/conf/haproxy-config.template
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ backend be_sni

frontend fe_sni
# terminate ssl on edge
bind 127.0.0.1:{{env "ROUTER_SERVICE_SNI_PORT" "10444"}} ssl no-sslv3 {{ if (len .DefaultCertificate) gt 0 }}crt {{.DefaultCertificate}}{{ else }}crt /var/lib/haproxy/conf/default_pub_keys.pem{{ end }} crt {{ $workingDir }}/certs accept-proxy
bind 127.0.0.1:{{env "ROUTER_SERVICE_SNI_PORT" "10444"}} ssl no-sslv3 {{ if (len .DefaultCertificate) gt 0 }}crt {{.DefaultCertificate}}{{ else }}crt /var/lib/haproxy/conf/default_pub_keys.pem{{ end }} crt-list /var/lib/haproxy/conf/cert_config.map accept-proxy
mode http

# Remove port from Host header
Expand Down Expand Up @@ -548,4 +548,24 @@ backend be_secure_{{$cfgIdx}}
{{$cfg.Host}}{{$cfg.Path}} {{$idx}}
{{ end }}
{{ end }}
{{ end }}{{/* end reencrypt passthrough map template */}}
{{ end }}{{/* end reencrypt map template */}}

{{/*
cert_config.map: contains a mapping of <cert-file> -> example.org
This map is used to present the appropriate cert
based on the sni header.
Note: It is sort of a reverse map for our case but the order
"<cert>: <domain-set>" is important as this allows us to use
wildcards and/or use a deny set with !<domain> in the future.
*/}}
{{ define "/var/lib/haproxy/conf/cert_config.map" }}
{{ $workingDir := .WorkingDir }}
{{ range $idx, $cfg := .State }}
Copy link
Contributor

Choose a reason for hiding this comment

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

is idx stable? When are the files on disk updated relative to the config being written and reloaded?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

idx stable - didn't get what you mean by that? The files on disk are actually created/updated as routes get processed.

Copy link
Contributor

Choose a reason for hiding this comment

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

we're mapping {{$idx}}.pem to a particular hostname. as routes get added/removed, will $idx refer to a different route, and will {{$idx}}.pem be overwritten with a different route's cert?

if that happens asynchronously to the way the config is generated and reloaded, what does haproxy do in the meantime? does it ignore changes to the certs in the dir? does it pick up file changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So that's the internally generated name of the route namespace+name, so it is unique for routes. So it is "stable".

As re: haproxy loading the cert - it would only do it now if there is an entry in the mapping file it loads at startup. New entries in the mapping file would only be "used" after the next reload. The flip side is on a route delete, the cert would be deleted before the reload.

Copy link
Contributor

Choose a reason for hiding this comment

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

that's the internally generated name of the route namespace+name, so it is unique for routes

Unique is good. How does the map behave if multiple routes have the same host but specify different certs?

on a route delete, the cert would be deleted before the reload.

do we know if that causes errors or falls back to the default cert or something else? Do we need to move cert deletions to occur after the template is generated and haproxy is reloaded?

{{ if and (ne $cfg.Host "") (or (eq $cfg.TLSTermination "edge") (eq $cfg.TLSTermination "reencrypt")) }}
{{ $cert := index $cfg.Certificates $cfg.Host }}
{{ if ne $cert.Contents "" }}
{{$workingDir}}/certs/{{$idx}}.pem {{$cfg.Host}}
{{ end }}
{{ end }}
{{ end }}
{{ end }}{{/* end cert_config map template */}}