You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There currently exists a timing window that can lead to client errors if you are using signed repo metadata with repo_gpgcheck=1. When you are using that option of course the server provides both the normal repomd.xml file and also a detached signature of it in repomd.xml.asc. Even if the server swaps out both files atomically on a repo update, an unlucky client can have received the old version of repomd.xml and the new version of repomd.xml.asc, if its requests happened to come on either side the update instant. The signature will then fail to verify and the client will return an error. Furthermore if the server is using any type of caching system or CDN, this mis-match can get persisted in the cache up to the TTL of the files if you are unlucky, causing many client errors and making the repo essentially unavailable for a period of time.
Unlike the other metadata files, there is no hash information in the name of repomd.xml.asc, or any other indication of what version of the file you want. This is likely because there is a chicken-and-egg problem of writing this info into repomd.xml: the file must exist first before you can sign it or calculate its hash, and the act of adding that information back in to repomd.xml invalidates the signature or changes the hash.
I furthermore assume that this is a detached signature in the first place instead of simply clearsigning repomd.xml to keep it one atomic file because there were worries about backwards-incompatibility with old clients.
Reproduction steps
See description.
Expected behavior
Any change which would indicate which version of repomd.xml.asc that you need to the server is a potential fix, but I think there are three main possibilities:
Changing the name of the file like you do with other metadata files, with the name calculated client-side somehow.
Adding a header to the request.
Adding a query parameter to the request.
In particular for backwards compatibility and ease-of-update, I suggest we do number 3, simply take the Last-Modified header value on the repomd.xml response, and add it as a query parameter on the repomd.xml.asc request: .../repomd.xml.asc?repomd_last_modified=<header value>
Almost every webserver simply ignores extra unexpected query params, so this should not break anything. On the off chance that it does and a server responds with a 4xx HTTP code, tdnf could simply revert back to today's behavior and request the file without the query param.
By contrast, caches / CDNs typically do include the query params as part of the cache key by default.
By including the information on whichrepomd.xml file you have in the cache key for repomd.xml.asc we are creating different cached versions of the file, and the client will automatically receive the correct one and proceed successfully if these cache keys are already populated. If there is no cache involved and a server is responding to every request directly, at least they are in no worse position than they were before, and they can teach their server to respond appropriately to the query param if they wish.
There is still a possible timing window here where bad pairs can get cached if both cache TTLs time out and a client re-fills the cache with an old version of repomd.xml and a new version of repomd.xml.asc?repomd_last_modified=123from a server that is ignoring the query string. However this gives servers the ability to close this gap permanently and respond correctly to every request, by doing either:
Teach the webserver to respond correctly to the query param, or
Increase the cache TTL on */repomd.xml.asc?repomd_last_modified=* to more than double the TTL of repomd.xml, eliminating the overlapping timing window where it's possible to cache incompatible versions of the files.
Describe the bug
There currently exists a timing window that can lead to client errors if you are using signed repo metadata with
repo_gpgcheck=1
. When you are using that option of course the server provides both the normalrepomd.xml
file and also a detached signature of it inrepomd.xml.asc
. Even if the server swaps out both files atomically on a repo update, an unlucky client can have received the old version ofrepomd.xml
and the new version ofrepomd.xml.asc
, if its requests happened to come on either side the update instant. The signature will then fail to verify and the client will return an error. Furthermore if the server is using any type of caching system or CDN, this mis-match can get persisted in the cache up to the TTL of the files if you are unlucky, causing many client errors and making the repo essentially unavailable for a period of time.Unlike the other metadata files, there is no hash information in the name of
repomd.xml.asc
, or any other indication of what version of the file you want. This is likely because there is a chicken-and-egg problem of writing this info intorepomd.xml
: the file must exist first before you can sign it or calculate its hash, and the act of adding that information back in torepomd.xml
invalidates the signature or changes the hash.I furthermore assume that this is a detached signature in the first place instead of simply clearsigning
repomd.xml
to keep it one atomic file because there were worries about backwards-incompatibility with old clients.Reproduction steps
See description.
Expected behavior
Any change which would indicate which version of
repomd.xml.asc
that you need to the server is a potential fix, but I think there are three main possibilities:In particular for backwards compatibility and ease-of-update, I suggest we do number 3, simply take the
Last-Modified
header value on therepomd.xml
response, and add it as a query parameter on therepomd.xml.asc
request:.../repomd.xml.asc?repomd_last_modified=<header value>
4xx
HTTP code, tdnf could simply revert back to today's behavior and request the file without the query param.By including the information on which
repomd.xml
file you have in the cache key forrepomd.xml.asc
we are creating different cached versions of the file, and the client will automatically receive the correct one and proceed successfully if these cache keys are already populated. If there is no cache involved and a server is responding to every request directly, at least they are in no worse position than they were before, and they can teach their server to respond appropriately to the query param if they wish.There is still a possible timing window here where bad pairs can get cached if both cache TTLs time out and a client re-fills the cache with an old version of
repomd.xml
and a new version ofrepomd.xml.asc?repomd_last_modified=123
from a server that is ignoring the query string. However this gives servers the ability to close this gap permanently and respond correctly to every request, by doing either:*/repomd.xml.asc?repomd_last_modified=*
to more than double the TTL ofrepomd.xml
, eliminating the overlapping timing window where it's possible to cache incompatible versions of the files.Additional context
I have filed a corresponding bug against
dnf
here:rpm-software-management/libdnf#1664
The text was updated successfully, but these errors were encountered: