def collection_auth_check(request): ''' check permissions and return a collection id (cid) if a collection exists and the user has permission to upload. If not, a permission denied is returned. ''' auth = request.META.get('HTTP_AUTHORIZATION', None) # Load the body, which is json with variables body_unicode = request.body.decode('utf-8') body = json.loads(body_unicode) # Get variables tag = body.get('tag', 'latest') name = body.get('name') collection_name = format_collection_name(body.get('collection')) print(tag, name, collection_name, auth, body) # Authentication always required for push if auth is None: raise PermissionDenied(detail="Authentication Required") owner = get_request_user(auth) timestamp = generate_timestamp() payload = "push|%s|%s|%s|%s|" % (collection_name, timestamp, name, tag) # Validate Payload print(payload) if not validate_request(auth, payload, "push", timestamp): raise PermissionDenied(detail="Unauthorized") try: collection = Collection.objects.get(name=collection_name) except Collection.DoesNotExist: collection = None # Validate User Permissions, either for creating collection or adding # Here we have permission if: # 1- user collections are enabled with USER_COLLECTIONS # 2- the user is a superuser or staff # 3- the user is owner of a collection if not has_permission(auth, collection, pull_permission=False): raise PermissionDenied(detail="Unauthorized") # If the user cannot create a new collection if not owner.has_create_permission(): raise PermissionDenied(detail="Unauthorized") # If we get here user has create permission, does collection exist? if collection is None: collection = Collection.objects.create(name=collection_name, secret=str(uuid.uuid4())) collection.save() collection.owners.add(owner) collection.save() # Return json response with collection id return JsonResponse({'cid': collection.id})
def _container_get(request, container, name=None, tag=None): '''container get is the shared function for getting a container based on a name or an id. It validates the request and returns a response. Parameters ========== request: the request from the view with the user container: the container object to check ''' if container is None: raise NotFound if name is None: name = container.name if tag is None: tag = container.tag # The user isn't allowed to get more than the limit if container.get_count >= container.get_limit: return Response(429) if container.collection.get_count >= container.collection.get_limit: return Response(429) # All public images are pull-able is_private = container.collection.private if not is_private: serializer = SingleContainerSerializer(container) return Response(serializer.data) # Determine if user has permission to get if private auth = request.META.get('HTTP_AUTHORIZATION') if auth is None: print("Auth is None") raise PermissionDenied(detail="Authentication Required") # Validate User Permissions - must have view to pull private image if not has_permission(auth, container.collection): print("Does not have permission") raise PermissionDenied(detail="Unauthorized") timestamp = generate_timestamp() payload = "pull|%s|%s|%s|%s|" % (container.collection.name, timestamp, name, tag) if validate_request(auth, payload, "pull", timestamp): serializer = SingleContainerSerializer(container) return Response(serializer.data) return Response(400)
def perform_create(self, serializer): tag = self.request.data.get('tag', 'latest') name = self.request.data.get('name') auth = self.request.META.get('HTTP_AUTHORIZATION', None) collection_name = self.request.data.get('collection') # Authentication always required for push if auth is None: raise PermissionDenied(detail="Authentication Required") owner = get_request_user(auth) timestamp = generate_timestamp() payload = "push|%s|%s|%s|%s|" % (collection_name, timestamp, name, tag) # Validate Payload if not validate_request(auth, payload, "push", timestamp): raise PermissionDenied(detail="Unauthorized") create_new = False try: collection = Collection.objects.get(name=collection_name) # Only owners can push if not owner in collection.owners.all(): raise PermissionDenied(detail="Unauthorized") except Collection.DoesNotExist: collection = None create_new = True # Validate User Permissions if not has_permission(auth, collection, pull_permission=False): raise PermissionDenied(detail="Unauthorized") if collection is not None: try: container = Container.objects.get(collection=collection, name=name, tag=tag) if container.frozen is False: create_new = True except Container.DoesNotExist: create_new = True # New collection, pusher is owner if create_new is True: serializer.save(datafile=self.request.data.get('datafile'), collection=self.request.data.get('collection'), tag=self.request.data.get('tag', 'latest'), name=self.request.data.get('name'), owner_id=owner.id, metadata=self.request.data.get('metadata')) else: raise PermissionDenied(detail="%s is frozen, push not allowed." % container.get_short_uri())
def upload_complete(request): '''view called on /api/upload/complete after nginx upload module finishes. ''' from shub.apps.api.actions.create import upload_container if request.method == "POST": path = request.POST.get('file1.path') size = request.POST.get('file1.size') cid = request.POST.get('collection') filename = request.POST.get('file1.name') name = request.POST.get('name') version = request.POST.get('file1.md5') auth = request.META.get('HTTP_AUTHORIZATION', None) tag = request.POST.get('tag') csrftoken = request.META.get('CSRF_COOKIE') if auth is None and csrftoken is None: if os.path.exists(filename): os.remove(path) raise PermissionDenied(detail="Authentication Required") if DISABLE_BUILDING: if os.path.exists(filename): os.remove(path) raise PermissionDenied(detail="Uploading is disabled.") # at this point, the collection MUST exist try: collection = Collection.objects.get(id=cid) except Collection.DoesNotExist: raise PermissionDenied(detail="Authentication Required") # If not defined, coming from terminal web_interface = True if csrftoken is None: web_interface = False owner = get_request_user(auth) timestamp = generate_timestamp() payload = "upload|%s|%s|%s|%s|" % (collection.name, timestamp, name, tag) # Validate Payload if not validate_request(auth, payload, "upload", timestamp): raise PermissionDenied(detail="Unauthorized") if not has_permission(auth, collection, pull_permission=False): raise PermissionDenied(detail="Unauthorized") else: owner = request.user # If tag is provided, add to name if tag is not None: name = "%s:%s" % (name, tag) # Expected params are upload_id, name, md5, and cid message = upload_container(cid=collection.id, user=owner, version=version, upload_id=path, name=name, size=size) # If the function doesn't return a message (None), indicates success if message is None: message = "Upload Complete" if web_interface is True: messages.info(request, message) return redirect(collection.get_absolute_url()) return JsonResponse({"message": message}) return redirect('collections')
def perform_create(self, serializer): print(self.request.data) tag = self.request.data.get('tag', 'latest') name = self.request.data.get('name') auth = self.request.META.get('HTTP_AUTHORIZATION', None) collection_name = self.request.data.get('collection') # Building is disabled if DISABLE_BUILDING: raise PermissionDenied(detail="Building is disabled.") # Authentication always required for push if auth is None: print("auth is None") raise PermissionDenied(detail="Authentication Required") owner = get_request_user(auth) timestamp = generate_timestamp() payload = "build|%s|%s|%s|%s|" %(collection_name, timestamp, name, tag) # Validate Payload if not validate_request(auth, payload, "build", timestamp): print("auth is not valid for build") raise PermissionDenied(detail="Unauthorized") # Does the user have create permission? if not owner.has_create_permission(): print("owned doesnt have create permission") raise PermissionDenied(detail="Unauthorized Create Permission") # Are we over the build limit? if is_over_limit(): message = ("Registry concurrent build limit is " + "%s" % SREGISTRY_GOOGLE_BUILD_LIMIT + ". Please try again later.") print(message) raise PermissionDenied(detail=message) create_new = False # Determine the collection to build the recipe to try: collection = Collection.objects.get(name=collection_name) # Only owners can push to existing collections if not owner in collection.owners.all(): print("user not in owners") raise PermissionDenied(detail="Unauthorized") except Collection.DoesNotExist: print("collection does not exist") raise PermissionDenied(detail="Not Found") # Validate User Permissions if not has_permission(auth, collection, pull_permission=False): print("user does not have permissions.") raise PermissionDenied(detail="Unauthorized") # The collection must exist when we get here try: container = Container.objects.get(collection=collection, name=name, tag=tag) if not container.frozen: create_new = True except Container.DoesNotExist: create_new = True # Create the recipe to trigger a build print(self.request.data.get('datafile')) if create_new is True: serializer.save(datafile=self.request.data.get('datafile'), collection=self.request.data.get('collection'), tag=self.request.data.get('tag', 'latest'), name=self.request.data.get('name'), owner_id=owner.id) else: raise PermissionDenied(detail="%s is frozen, push not allowed." % container.get_short_uri())