Project with multiple domains failing with pages cache enabled
The problem
The root cause of the "multiple domains on the same project" failing when the cache is enabled, is that we're caching the /api/internal/pages
payload under the project id, among other stuff. Which means that the cached certificates are always returned for all the domains in the same project.
For example, I added two domains in the same project:
domain | cert (first line) |
---|---|
foo.bar | MIIDYTCCAkmgAwIBAgIUIdH6Eae0BfFz+tT7CoivAZBWPi8wDQYJKoZIhvcNAQEL |
aaaa.bbbb | MIIDazCCAlOgAwIBAgIUTkwJffm429SM4IytBUhMVseOJnEwDQYJKoZIhvcNAQEL |
- With the cache disabled
$ curl -s "http://gdk.test:3000/api/v4/internal/pages?host=aaaa.bbbb" | jq '.certificate | split("\r\n")[1] '
"MIIDazCCAlOgAwIBAgIUTkwJffm429SM4IytBUhMVseOJnEwDQYJKoZIhvcNAQEL"
$ curl -s "http://gdk.test:3000/api/v4/internal/pages?host=foo.bar" | jq '.certificate | split("\r\n")[1] '
"MIIDYTCCAkmgAwIBAgIUIdH6Eae0BfFz+tT7CoivAZBWPi8wDQYJKoZIhvcNAQEL"
- With the cache enabled
$ curl -s "http://gdk.test:3000/api/v4/internal/pages?host=aaaa.bbbb" | jq '.certificate | split("\r\n")[1] '
"MIIDYTCCAkmgAwIBAgIUIdH6Eae0BfFz+tT7CoivAZBWPi8wDQYJKoZIhvcNAQEL"
$ curl -s "http://gdk.test:3000/api/v4/internal/pages?host=foo.bar" | jq '.certificate | split("\r\n")[1] '
"MIIDYTCCAkmgAwIBAgIUIdH6Eae0BfFz+tT7CoivAZBWPi8wDQYJKoZIhvcNAQEL"
Proposed Solution
The cache is created in the lib/api/internal/pages
from either the Namespace
or the PagesDomain
.
Namespace.find_by_pages_host(params[:host]) || PagesDomain.find_by_domain_case_insensitive(params[:host])
When the cache was created from the PagesDomain
, we were using the project.id
associated to the PagesDomain
in the cache key. Since one project might have many PageDomain
s, the solution would be to, instead of using the project.id
, use the domain.id
in the cache key.
This way, instead of Gitlab::Pages::CacheControl.for_project
we could have Gitlab::Pages::CacheControl.for_domain
.
One important detail is to ensure that all the events that invalidate the cache relate to a PagesDomain
should now also expose the domain.id
.