Fix Akamai OCSP purging code (#2531)
Purge both query encoded and un-encoded OCSP GET URLs and fix a typo in the POST body key. Since there is no public documentation of how the latter Akamai feature works we were unable to confirm that the previously spelling of `body-mdy` was a typo of `body-md5` but active testing against the staging environment and the Akamai API has confirmed that it was. Fixes #2528.
This commit is contained in:
parent
00d11f126b
commit
a0da51ee7b
|
|
@ -207,12 +207,28 @@ func reverseBytes(b []byte) []byte {
|
|||
return b
|
||||
}
|
||||
|
||||
func generatePOSTURL(der []byte, ocspServer string) string {
|
||||
// Generate POST url, format is the URL that was POST'd to with a query string with
|
||||
// the parameter 'body-mdy' and the value of the first two uint32s in little endian
|
||||
// order in hex of the MD5 hash of the OCSP request body.
|
||||
hash := md5.Sum(der)
|
||||
return fmt.Sprintf("%s?body-mdy=%x%x", ocspServer, reverseBytes(hash[0:4]), reverseBytes(hash[4:8]))
|
||||
func generateOCSPCacheKeys(req []byte, ocspServer string) []string {
|
||||
hash := md5.Sum(req)
|
||||
encReq := base64.StdEncoding.EncodeToString(req)
|
||||
return []string{
|
||||
// Generate POST key, format is the URL that was POST'd to with a query string with
|
||||
// the parameter 'body-md5' and the value of the first two uint32s in little endian
|
||||
// order in hex of the MD5 hash of the OCSP request body.
|
||||
//
|
||||
// There is no public documentation of this feature that has been published by Akamai
|
||||
// as far as we are aware.
|
||||
fmt.Sprintf("%s?body-md5=%x%x", ocspServer, reverseBytes(hash[0:4]), reverseBytes(hash[4:8])),
|
||||
// RFC 2560 and RFC 5019 state OCSP GET URLs 'MUST properly url-encode the base64
|
||||
// encoded' request but a large enough portion of tools do not properly do this
|
||||
// (~10% of GET requests we receive) such that we must purge both the encoded
|
||||
// and un-encoded URLs.
|
||||
//
|
||||
// Due to Akamai proxy/cache behavior which collapses '//' -> '/' we also
|
||||
// collapse double slashes in the un-encoded URL so that we properly purge
|
||||
// what is stored in the cache.
|
||||
fmt.Sprintf("%s%s", ocspServer, strings.Replace(encReq, "//", "/", -1)),
|
||||
fmt.Sprintf("%s%s", ocspServer, url.QueryEscape(encReq)),
|
||||
}
|
||||
}
|
||||
|
||||
// sendPurge should only be called as a Goroutine as it will block until the purge
|
||||
|
|
@ -237,11 +253,7 @@ func (updater *OCSPUpdater) sendPurge(der []byte) {
|
|||
ocspServer += "/"
|
||||
}
|
||||
// Generate GET url
|
||||
urls = append(
|
||||
urls,
|
||||
fmt.Sprintf("%s%s", ocspServer, url.QueryEscape(base64.StdEncoding.EncodeToString(req))),
|
||||
)
|
||||
urls = append(urls, generatePOSTURL(der, ocspServer))
|
||||
urls = append(generateOCSPCacheKeys(req, ocspServer))
|
||||
}
|
||||
|
||||
err = updater.ccu.Purge(urls)
|
||||
|
|
|
|||
|
|
@ -857,11 +857,15 @@ func TestReverseBytes(t *testing.T) {
|
|||
test.AssertDeepEquals(t, reverseBytes(a), []byte{3, 2, 1, 0})
|
||||
}
|
||||
|
||||
func TestGeneratePOSTURL(t *testing.T) {
|
||||
der := []byte{0}
|
||||
test.AssertEquals(
|
||||
func TestGenerateOCSPCacheKeys(t *testing.T) {
|
||||
der := []byte{105, 239, 255}
|
||||
test.AssertDeepEquals(
|
||||
t,
|
||||
generatePOSTURL(der, "ocsp.invalid/"),
|
||||
"ocsp.invalid/?body-mdy=ad85b89389a00dfe",
|
||||
generateOCSPCacheKeys(der, "ocsp.invalid/"),
|
||||
[]string{
|
||||
"ocsp.invalid/?body-md5=d6101198a9d9f1f6",
|
||||
"ocsp.invalid/ae/",
|
||||
"ocsp.invalid/ae%2F%2F",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue