Automatic HTTPS certificate creation/renewal 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 and renewed manually. Using Let's Encrypt, we can provide a simple way to obtain/renew the certificate and automatically configure it on Pages.
Note: Let's Encrypt support for the generic base domain is a separate issue discussed in omnibus-gitlab#3342.
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. It's important it's on a per-domain basis because different users will have different domains with different requirements.
Users should be able to configure Let's Encrypt in the Application settings by filling in an email for alerts, and accepting Let's Encrypt terms of service. Once configured and enabled, users will have the option to toggle Let's Encrypt on/off on project Pages settings.
Users that have no access permission to Let's Encrypt should not be able to manage it.
UX Proposal
NOTE: In case the copy in the prototypes is different from the one in the acceptance criteria below, please consider the written acceptance criteria as the SSO and not the prototypes.
Other notes:
- To reduce security risks we should never make the let's encrypt 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 not be visible for let's encrypt certificates, so we should not give users ability to see uploaded key on domain edit page.
- Enabling it for the first time may take a bit of time. We need to show a warning that the certificate is being fetched and the site won't work until that is done (~15m)
- If the user deselects automatic configuration, everything should turn back to the way it was and we should release the certificate with LetsEncrypt.
- Add a helper text next to the certificates section with some information regarding what they are and what they do, and link it to: https://gitlab.com/help/user/project/pages/getting_started_part_three.md#adding-certificates-to-your-project. This way we provide more context about the certificates. It should read:
Learn more about adding certificates to your project following the [documentation on GitLab pages].
Implementation Plan
gitlab-pages gitlab-pages#165 (closed)
-
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.
What does success look like, and how can we measure that?
Measure users with this feature turned on
Unfinished parts
gitlab-pages!141 (merged) -gitlab-pagesgo part,ready to be merged, waits for following MR to omnibus to be readyomnibus-gitlab!3314 (merged) - omnibus support for newgitlab-pagesconfig paramsin devhttps://gitlab.com/gitlab-org/gitlab-ce/merge_requests/26438 - frontend part,in review, should be merged soonhttps://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27811/diffs - main CE part,in reviewhttps://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28855 - fix of already merged parts,in reviewhttps://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28743 - store valid period for ssl cert,in reviewhttps://gitlab.com/gitlab-org/gitlab-ce/merge_requests/29359 - fixes follow ups(https://gitlab.com/gitlab-org/gitlab-ce/issues/61752, https://gitlab.com/gitlab-org/gitlab-ce/issues/61500, https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27947)in reviewhttps://gitlab.com/gitlab-org/gitlab-ce/merge_requests/29363 - scheduling obtaining/renewal of certificates,in reviewhttps://gitlab.com/gitlab-org/gitlab-ce/merge_requests/29609 - make related feature flag "aware of project" - should be small, but would be easier to do when previous 2 MR got merged,in reviewdo not get certs for not verified domains -in review(also in https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/29609)https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/29675 - reduce waiting time(automatically schedule subsequent stages of obtaining certificate) -in reviewactually rollout changes on production (may be we need a separate issue here)write documentation -not started, this can be done simultaneously with production rollout
points for future documentation
- If a certificate is obtained through LetsEncrypt and then LetsEncrypt integration is disabled in GitLab admin settings, the obtained certificate will continue to work until replaced manually.


