Prevent invalid tags on builds

Fixes #1632
This commit is contained in:
Joseph Schorr 2016-07-25 17:50:35 -07:00
parent 640012103c
commit 0fe3e6510a
5 changed files with 41 additions and 5 deletions

View file

@ -8,6 +8,7 @@ from data import model
from data.database import db
from auth.auth_context import get_authenticated_user
from endpoints.notificationhelper import spawn_notification
from util.names import escape_tag
logger = logging.getLogger(__name__)
@ -160,7 +161,7 @@ class PreparedBuild(object):
if self._tags:
raise Exception('Property tags already set')
self._tags = list(value)
self._tags = [escape_tag(tag, default='latest') for tag in value]
@property
def build_name(self):

View file

@ -24,6 +24,7 @@ from endpoints.v2.errors import (BlobUnknown, ManifestInvalid, ManifestUnknown,
from endpoints.trackhelper import track_and_log
from endpoints.notificationhelper import spawn_notification
from util.registry.replication import queue_storage_replication
from util.names import VALID_TAG_PATTERN
from digest import digest_tools
from data import model
from data.database import RepositoryTag
@ -31,8 +32,6 @@ from data.database import RepositoryTag
logger = logging.getLogger(__name__)
VALID_TAG_PATTERN = r'[\w][\w.-]{0,127}'
BASE_MANIFEST_ROUTE = '/<repopath:repository>/manifests/<regex("{0}"):manifest_ref>'
MANIFEST_DIGEST_ROUTE = BASE_MANIFEST_ROUTE.format(digest_tools.DIGEST_PATTERN)
MANIFEST_TAGNAME_ROUTE = BASE_MANIFEST_ROUTE.format(VALID_TAG_PATTERN)

View file

@ -50,3 +50,8 @@ class TestDigestPath(unittest.TestCase):
for digest, path in examples:
self.assertEquals(content_path(digest), path)
if __name__ == '__main__':
unittest.main()

20
test/test_names.py Normal file
View file

@ -0,0 +1,20 @@
import unittest
from util.names import escape_tag
class TestEscapeTag(unittest.TestCase):
def assertTag(self, input_tag, expected):
self.assertEquals(expected, escape_tag(input_tag))
def test_basic_tag(self):
self.assertTag('latest', 'latest')
self.assertTag('latest124', 'latest124')
self.assertTag('5de1e98d', '5de1e98d')
def test_invalid_tag(self):
self.assertTag('detailed_view#61', 'detailed_view_61')
self.assertTag('-detailed_view#61', '_detailed_view_61')
if __name__ == '__main__':
unittest.main()

View file

@ -1,15 +1,26 @@
import urllib
import re
from functools import wraps
from uuid import uuid4
REPOSITORY_NAME_REGEX = re.compile(r'^[\.a-zA-Z0-9_-]+$')
TAG_REGEX = re.compile(r'^[\w][\w\.-]{0,127}$')
VALID_TAG_PATTERN = r'[\w][\w.-]{0,127}'
FULL_TAG_PATTERN = r'^[\w][\w.-]{0,127}$'
TAG_REGEX = re.compile(FULL_TAG_PATTERN)
TAG_ERROR = ('Invalid tag: must match [A-Za-z0-9_.-], NOT start with "." or "-", '
'and can contain 1-128 characters')
def escape_tag(tag, default='latest'):
""" Escapes a Docker tag, ensuring it matches the tag regular expression. """
if not tag:
return default
tag = re.sub(r'^[^\w]', '_', tag)
tag = re.sub(r'[^\w\.-]', '_', tag)
return tag[0:127]
def parse_namespace_repository(repository, library_namespace, include_tag=False):
parts = repository.rstrip('/').split('/', 1)