Skip to content

Commit

Permalink
Accept and ignore 'null' as value for X-Registry-Auth
Browse files Browse the repository at this point in the history
docker-client is a library written in Java and used in Eclipse to
speak with Docker API. When endpoint /images/search is called,
HTTP header attribute X-Registry-Auth has value "null". This is for
sure wrong but Docker tolerates this value, and call works. With this
patch call works also with Podman. containers#7857

Signed-off-by: Milivoje Legenovic <[email protected]>
  • Loading branch information
mlegenovic authored and Achilleas Tzenetopoulos committed Jan 26, 2021
1 parent 496180d commit d89174a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
8 changes: 6 additions & 2 deletions pkg/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,9 @@ func imageAuthToDockerAuth(authConfig types.DockerAuthConfig) dockerAPITypes.Aut
func singleAuthHeader(r *http.Request) (map[string]types.DockerAuthConfig, error) {
authHeader := r.Header.Get(string(XRegistryAuthHeader))
authConfig := dockerAPITypes.AuthConfig{}
if len(authHeader) > 0 {
// Accept "null" and handle it as empty value for compatibility reason with Docker.
// Some java docker clients pass this value, e.g. this one used in Eclipse.
if len(authHeader) > 0 && authHeader != "null" {
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authHeader))
if err := json.NewDecoder(authJSON).Decode(&authConfig); err != nil {
return nil, err
Expand All @@ -312,7 +314,9 @@ func singleAuthHeader(r *http.Request) (map[string]types.DockerAuthConfig, error
// The header content is a map[string]DockerAuthConfigs.
func multiAuthHeader(r *http.Request) (map[string]types.DockerAuthConfig, error) {
authHeader := r.Header.Get(string(XRegistryAuthHeader))
if len(authHeader) == 0 {
// Accept "null" and handle it as empty value for compatibility reason with Docker.
// Some java docker clients pass this value, e.g. this one used in Eclipse.
if len(authHeader) == 0 || authHeader == "null" {
return nil, nil
}

Expand Down
46 changes: 46 additions & 0 deletions test/apiv2/rest_api/test_rest_v2_0_0.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,52 @@ def test_pull(self):
self.assertTrue(keys["stream"], "Expected to find stream progress stanza's")

def test_search_compat(self):
url = PODMAN_URL + "/v1.40/images/search"
# Had issues with this test hanging when repositories not happy
def do_search1():
payload = {'term': 'alpine'}
r = requests.get(url, params=payload, timeout=5)
self.assertEqual(r.status_code, 200, r.text)
objs = json.loads(r.text)
self.assertIn(type(objs), (list,))

def do_search2():
payload = {'term': 'alpine', 'limit': 1}
r = requests.get(url, params=payload, timeout=5)
self.assertEqual(r.status_code, 200, r.text)
objs = json.loads(r.text)
self.assertIn(type(objs), (list,))
self.assertEqual(len(objs), 1)

def do_search3():
payload = {'term': 'alpine', 'filters': {'is-official': True}}
r = requests.get(url, params=payload, timeout=5)
self.assertEqual(r.status_code, 200, r.text)
objs = json.loads(r.text)
self.assertIn(type(objs), (list,))
# TODO: Request should return only one item, but it returns more. For now this check is commented out.
# self.assertEqual(len(objs), 1)

def do_search4():
headers = {'X-Registry-Auth': 'null'}
payload = {'term': 'alpine'}
r = requests.get(url, params=payload, headers=headers, timeout=5)
self.assertEqual(r.status_code, 200, r.text)

def do_search5():
headers = {'X-Registry-Auth': 'invalid value'}
payload = {'term': 'alpine'}
r = requests.get(url, params=payload, headers=headers, timeout=5)
self.assertEqual(r.status_code, 400, r.text)

search_methods = [do_search1, do_search2, do_search3, do_search4, do_search5]
for search_method in search_methods:
search = Process(target=search_method)
search.start()
search.join(timeout=10)
self.assertFalse(search.is_alive(), "/images/search took too long")

def test_search_compat_with_(self):
# Had issues with this test hanging when repositories not happy
def do_search():
r = requests.get(PODMAN_URL + "/v1.40/images/search?term=alpine", timeout=5)
Expand Down

0 comments on commit d89174a

Please sign in to comment.