Beispiel #1
0
    def post(self, namespace, repository, tag):
        """
        Restores a repository tag back to a previous image in the repository.
        """
        repo_ref = registry_model.lookup_repository(namespace, repository)
        if repo_ref is None:
            raise NotFound()

        # Restore the tag back to the previous image.
        image_id = request.get_json().get("image", None)
        manifest_digest = request.get_json().get("manifest_digest", None)

        if image_id is None and manifest_digest is None:
            raise InvalidRequest("Missing manifest_digest")

        # Data for logging the reversion/restoration.
        username = get_authenticated_user().username
        log_data = {
            "username": username,
            "repo": repository,
            "tag": tag,
            "image": image_id,
            "manifest_digest": manifest_digest,
        }

        manifest_or_legacy_image = None
        if manifest_digest is not None:
            manifest_or_legacy_image = registry_model.lookup_manifest_by_digest(
                repo_ref,
                manifest_digest,
                allow_dead=True,
                require_available=True)
        elif image_id is not None:
            manifest_or_legacy_image = registry_model.get_legacy_image(
                repo_ref, image_id)

        if manifest_or_legacy_image is None:
            raise NotFound()

        if not registry_model.retarget_tag(
                repo_ref,
                tag,
                manifest_or_legacy_image,
                storage,
                docker_v2_signing_key,
                is_reversion=True,
        ):
            raise InvalidRequest("Could not restore tag")

        log_action("revert_tag", namespace, log_data, repo_name=repository)

        return {}
Beispiel #2
0
    def commit_tag_and_manifest(self, tag_name, layer):
        """
        Commits a new tag + manifest for that tag to the repository with the given name, pointing to
        the given layer.
        """
        legacy_image = registry_model.get_legacy_image(self._repository_ref, layer.layer_id)
        if legacy_image is None:
            return None

        tag = registry_model.retarget_tag(
            self._repository_ref, tag_name, legacy_image, self._storage, self._legacy_signing_key
        )
        if tag is None:
            return None

        self._builder_state.tags[tag_name] = tag._db_id
        self._save_to_session()
        return tag
Beispiel #3
0
def put_tag(namespace_name, repo_name, tag):
    permission = ModifyRepositoryPermission(namespace_name, repo_name)
    repository_ref = registry_model.lookup_repository(namespace_name,
                                                      repo_name,
                                                      kind_filter="image")

    if permission.can() and repository_ref is not None:
        if not TAG_REGEX.match(tag):
            abort(400, TAG_ERROR)

        image_id = json.loads(request.data)

        # Check for the image ID first in a builder (for an in-progress push).
        builder = lookup_manifest_builder(repository_ref,
                                          session.get("manifest_builder"),
                                          storage, docker_v2_signing_key)
        if builder is not None:
            layer = builder.lookup_layer(image_id)
            if layer is not None:
                commited_tag = builder.commit_tag_and_manifest(tag, layer)
                if commited_tag is None:
                    abort(400)

                return make_response("Created", 200)

        # Check if there is an existing image we should use (for PUT calls outside of a normal push
        # operation).
        legacy_image = registry_model.get_legacy_image(repository_ref,
                                                       image_id)
        if legacy_image is None:
            abort(400)

        if (registry_model.retarget_tag(repository_ref, tag, legacy_image,
                                        storage, docker_v2_signing_key) is
                None):
            abort(400)

        return make_response("Created", 200)

    abort(403)
Beispiel #4
0
    def put(self, namespace, repository, tag):
        """
        Change which image a tag points to or create a new tag.
        """
        if not TAG_REGEX.match(tag):
            abort(400, TAG_ERROR)

        repo_ref = registry_model.lookup_repository(namespace, repository)
        if repo_ref is None:
            raise NotFound()

        if "expiration" in request.get_json():
            tag_ref = registry_model.get_repo_tag(repo_ref, tag)
            if tag_ref is None:
                raise NotFound()

            expiration = request.get_json().get("expiration")
            expiration_date = None
            if expiration is not None:
                try:
                    expiration_date = datetime.utcfromtimestamp(
                        float(expiration))
                except ValueError:
                    abort(400)

                if expiration_date <= datetime.now():
                    abort(400)

            existing_end_ts, ok = registry_model.change_repository_tag_expiration(
                tag_ref, expiration_date)
            if ok:
                if not (existing_end_ts is None and expiration_date is None):
                    log_action(
                        "change_tag_expiration",
                        namespace,
                        {
                            "username": get_authenticated_user().username,
                            "repo": repository,
                            "tag": tag,
                            "namespace": namespace,
                            "expiration_date": expiration_date,
                            "old_expiration_date": existing_end_ts,
                        },
                        repo_name=repository,
                    )
            else:
                raise InvalidRequest(
                    "Could not update tag expiration; Tag has probably changed"
                )

        if "image" in request.get_json(
        ) or "manifest_digest" in request.get_json():
            existing_tag = registry_model.get_repo_tag(
                repo_ref, tag, include_legacy_image=True)

            manifest_or_image = None
            image_id = None
            manifest_digest = None

            if "manifest_digest" in request.get_json():
                manifest_digest = request.get_json()["manifest_digest"]
                manifest_or_image = registry_model.lookup_manifest_by_digest(
                    repo_ref, manifest_digest, require_available=True)
            else:
                image_id = request.get_json()["image"]
                manifest_or_image = registry_model.get_legacy_image(
                    repo_ref, image_id)

            if manifest_or_image is None:
                raise NotFound()

            existing_manifest = (
                registry_model.get_manifest_for_tag(existing_tag)
                if existing_tag else None)
            existing_manifest_digest = existing_manifest.digest if existing_manifest else None

            if not registry_model.retarget_tag(repo_ref, tag,
                                               manifest_or_image, storage,
                                               docker_v2_signing_key):
                raise InvalidRequest("Could not move tag")

            username = get_authenticated_user().username

            log_action(
                "move_tag" if existing_tag else "create_tag",
                namespace,
                {
                    "username": username,
                    "repo": repository,
                    "tag": tag,
                    "namespace": namespace,
                    "image": image_id,
                    "manifest_digest": manifest_digest,
                    "original_manifest_digest": existing_manifest_digest,
                },
                repo_name=repository,
            )

        return "Updated", 201
Beispiel #5
0
    def put(self, namespace, repository, tag):
        """ Change which image a tag points to or create a new tag."""
        if not TAG_REGEX.match(tag):
            abort(400, TAG_ERROR)

        repo_ref = registry_model.lookup_repository(namespace, repository)
        if repo_ref is None:
            raise NotFound()

        if 'expiration' in request.get_json():
            tag_ref = registry_model.get_repo_tag(repo_ref, tag)
            if tag_ref is None:
                raise NotFound()

            expiration = request.get_json().get('expiration')
            expiration_date = None
            if expiration is not None:
                try:
                    expiration_date = datetime.utcfromtimestamp(
                        float(expiration))
                except ValueError:
                    abort(400)

                if expiration_date <= datetime.now():
                    abort(400)

            existing_end_ts, ok = registry_model.change_repository_tag_expiration(
                tag_ref, expiration_date)
            if ok:
                if not (existing_end_ts is None and expiration_date is None):
                    log_action(
                        'change_tag_expiration',
                        namespace, {
                            'username': get_authenticated_user().username,
                            'repo': repository,
                            'tag': tag,
                            'namespace': namespace,
                            'expiration_date': expiration_date,
                            'old_expiration_date': existing_end_ts
                        },
                        repo_name=repository)
            else:
                raise InvalidRequest(
                    'Could not update tag expiration; Tag has probably changed'
                )

        if 'image' in request.get_json(
        ) or 'manifest_digest' in request.get_json():
            existing_tag = registry_model.get_repo_tag(
                repo_ref, tag, include_legacy_image=True)

            manifest_or_image = None
            image_id = None
            manifest_digest = None

            if 'image' in request.get_json():
                image_id = request.get_json()['image']
                manifest_or_image = registry_model.get_legacy_image(
                    repo_ref, image_id)
            else:
                manifest_digest = request.get_json()['manifest_digest']
                manifest_or_image = registry_model.lookup_manifest_by_digest(
                    repo_ref, manifest_digest, require_available=True)

            if manifest_or_image is None:
                raise NotFound()

            # TODO: Remove this check once fully on V22
            existing_manifest_digest = None
            if existing_tag:
                existing_manifest = registry_model.get_manifest_for_tag(
                    existing_tag)
                existing_manifest_digest = existing_manifest.digest if existing_manifest else None

            if not registry_model.retarget_tag(repo_ref, tag,
                                               manifest_or_image, storage,
                                               docker_v2_signing_key):
                raise InvalidRequest('Could not move tag')

            username = get_authenticated_user().username

            log_action(
                'move_tag' if existing_tag else 'create_tag',
                namespace, {
                    'username':
                    username,
                    'repo':
                    repository,
                    'tag':
                    tag,
                    'namespace':
                    namespace,
                    'image':
                    image_id,
                    'manifest_digest':
                    manifest_digest,
                    'original_image':
                    (existing_tag.legacy_image.docker_image_id if existing_tag
                     and existing_tag.legacy_image_if_present else None),
                    'original_manifest_digest':
                    existing_manifest_digest,
                },
                repo_name=repository)

        return 'Updated', 201