Automatic HTTPS support for Pages custom domains
Description
GitLab Pages allows users to specify custom domains to access their websites. Those websites could be accessible via HTTPS, but a certificate must be provided manually.
Using Let's Encrypt, we can provide a simple way to obtain the certificate and automatically configure it on Pages.
Proposal
When a new custom domain is added and HTTPS is enabled, users can provide a certificate or choose to leverage Let's Encrypt to obtain one automatically. Certificates should be automatically managed for renewals if possible.
Note: Let's Encrypt support for the generic base domain is discussed in omnibus-gitlab#3342.
Implementation Plan
gitlab-pages gitlab-pages#165
- Changes so that it redirects any requests for unknown files matching the acme verification format:
GET mydomain.com/.well-known/acme-challenge/:acme_key
=>
301
Location: gitlab.com/-/acme-challenge/mydomain.com/:acme_key
gitlab-ce
-
AcmeChallengeController:- Looks up
PagesDomain#acme_key,PagesDomain#acme_account_keyand serves up the correct expected ACME response. - Importantly this should not serve up the certificate unless
PagesDomain#verified?to avoid any risk of us serving up SSL certificates for domains people do not own.
- Looks up
-
PagesDomainSslCertificateWorker- uses the ACME API to create
PagesDomain#acme_account_keyunless it exists. - uses the ACME API to generate a
PagesDomain#acme_keyand persists this to the DB so it can be used byAcmeChallengeController. - requests ACME API to now validate the domain and return certificate
- persists certificate to
PagesDomain#certificateand persists private key details - persists
PagesDomain#certificate_expires_atto be 90 days from now (or whatever ACME API returns) - kicks off
Projects::UpdatePagesConfigurationService
- uses the ACME API to create
-
PagesDomainSslCertificateCronWorkerwhich runs periodically to check for allPagesDomain.certificate_expires_atwithin the next 10 days and kicks offPagesDomainSslCertificateWorkerfork those.
Security Notes
- We really want to make sure there is no way people can exploit this to get SSL certificates for someone else' s domain
- Probably to reduce security risks we should never make the let's encrypt data and private key visible to any users at any time since they do not need to know it. Right now it would appear that private keys for certificates are visible when editing a pages domain. This should probably not be visible for let's encrypt certificates. In fact it's probably better it's not visible for any certificates.