Skip to content
This repository was archived by the owner on Sep 12, 2018. It is now read-only.

Commit 1ecaa79

Browse files
author
shin-
committed
validate_parent_access when trying to push a new layer
1 parent 6728ca4 commit 1ecaa79

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

docker_registry/images.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,8 @@ def put_image_json(image_id):
403403
parent_id = data.get('parent')
404404
if parent_id and not store.exists(store.image_json_path(data['parent'])):
405405
return toolkit.api_error('Image depends on a non existing parent')
406+
elif not toolkit.validate_parent_access(parent_id):
407+
return toolkit.api_error('Image depends on an unauthorized parent')
406408
json_path = store.image_json_path(image_id)
407409
mark_path = store.image_mark_path(image_id)
408410
if store.exists(json_path) and not store.exists(mark_path):

docker_registry/toolkit.py

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,39 @@ def check_session():
105105
return session.get('auth') is True
106106

107107

108+
def validate_parent_access(parent_id):
109+
cfg = config.load()
110+
if cfg.standalone:
111+
return True
112+
auth = _parse_auth_header()
113+
if not auth:
114+
return False
115+
full_repos_name = auth.get('repository', '').split('/')
116+
if len(full_repos_name) != 2:
117+
logger.debug('validate_token: Invalid repository field')
118+
return False
119+
index_endpoint = cfg.index_endpoint
120+
if index_endpoint is None:
121+
index_endpoint = 'https://index.docker.io'
122+
index_endpoint = index_endpoint.strip('/')
123+
url = '{0}/v1/images/{1}/{2}/{3}'.format(
124+
index_endpoint, full_repos_name[0], full_repos_name[1], parent_id
125+
)
126+
headers = {'Authorization': flask.request.headers.get('authorization')}
127+
resp = requests.get(url, verify=True, headers=headers)
128+
if resp.status_code != 200:
129+
logger.debug('validate_parent_access: index returned status {0}'.format(
130+
resp.status_code
131+
))
132+
return False
133+
try:
134+
return json.loads(resp.text).get('authorized', False)
135+
136+
except json.JSONDecodeError:
137+
logger.debug('validate_parent_access: Wrong response format')
138+
return False
139+
140+
108141
def validate_token(auth):
109142
full_repos_name = auth.get('repository', '').split('/')
110143
if len(full_repos_name) != 2:
@@ -150,18 +183,23 @@ def is_ssl():
150183
return False
151184

152185

153-
def check_token(args):
154-
cfg = config.load()
155-
if cfg.disable_token_auth is True or cfg.standalone is not False:
156-
return True
186+
def _parse_auth_header():
157187
auth = flask.request.headers.get('authorization', '')
158188
if auth.split(' ')[0].lower() != 'token':
159189
logger.debug('check_token: Invalid token format')
160-
return False
161-
logger.debug('args = {0}'.format(args))
190+
return None
162191
logger.debug('Auth Token = {0}'.format(auth))
163192
auth = dict(_re_authorization.findall(auth))
164193
logger.debug('auth = {0}'.format(auth))
194+
return auth
195+
196+
197+
def check_token(args):
198+
cfg = config.load()
199+
if cfg.disable_token_auth is True or cfg.standalone is not False:
200+
return True
201+
logger.debug('args = {0}'.format(args))
202+
auth = _parse_auth_header()
165203
if not auth:
166204
return False
167205
if 'namespace' in args and 'repository' in args:

0 commit comments

Comments
 (0)