126 lines
4.2 KiB
Python
126 lines
4.2 KiB
Python
import os
|
|
import tarfile
|
|
from tempfile import NamedTemporaryFile, TemporaryDirectory
|
|
from uuid import uuid4
|
|
|
|
from libcloud.storage.types import Provider
|
|
from libcloud.storage.providers import get_driver
|
|
|
|
from atst.domain.exceptions import UploadError
|
|
|
|
|
|
class CSPFileError(Exception):
|
|
pass
|
|
|
|
|
|
class FileProviderInterface:
|
|
_PERMITTED_MIMETYPES = ["application/pdf"]
|
|
|
|
def _enforce_mimetype(self, fyle):
|
|
# TODO: for hardening, we should probably use a better library for
|
|
# determining mimetype and not rely on FileUpload's determination
|
|
# TODO: we should set MAX_CONTENT_LENGTH in the config to prevent large
|
|
# uploads
|
|
if not fyle.mimetype in self._PERMITTED_MIMETYPES:
|
|
raise UploadError(
|
|
"could not upload {} with mimetype {}".format(
|
|
fyle.filename, fyle.mimetype
|
|
)
|
|
)
|
|
|
|
def upload(self, fyle): # pragma: no cover
|
|
"""Store the file object `fyle` in the CSP. This method returns the
|
|
object name that can be used to later look up the file."""
|
|
raise NotImplementedError()
|
|
|
|
def download(self, object_name): # pragma: no cover
|
|
"""Retrieve the stored file represented by `object_name`. Returns a
|
|
file object.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
|
|
def get_rackspace_container(provider, container=None, **kwargs):
|
|
if provider == "LOCAL": # pragma: no branch
|
|
kwargs["key"] = container
|
|
if not os.path.exists(container):
|
|
os.mkdir(container)
|
|
container = ""
|
|
|
|
driver = get_driver(getattr(Provider, provider))(**kwargs)
|
|
return driver.get_container(container)
|
|
|
|
|
|
class RackspaceFileProvider(FileProviderInterface):
|
|
def __init__(self, app):
|
|
self.container = get_rackspace_container(
|
|
provider=app.config.get("STORAGE_PROVIDER"),
|
|
container=app.config.get("STORAGE_CONTAINER"),
|
|
key=app.config.get("STORAGE_KEY"),
|
|
secret=app.config.get("STORAGE_SECRET"),
|
|
)
|
|
|
|
def upload(self, fyle):
|
|
self._enforce_mimetype(fyle)
|
|
|
|
object_name = uuid4().hex
|
|
with NamedTemporaryFile() as tempfile:
|
|
tempfile.write(fyle.stream.read())
|
|
tempfile.seek(0)
|
|
self.container.upload_object(
|
|
file_path=tempfile.name,
|
|
object_name=object_name,
|
|
extra={"acl": "private"},
|
|
)
|
|
return object_name
|
|
|
|
def download(self, object_name):
|
|
obj = self.container.get_object(object_name=object_name)
|
|
with NamedTemporaryFile() as tempfile:
|
|
obj.download(tempfile.name, overwrite_existing=True)
|
|
return open(tempfile.name, "rb")
|
|
|
|
|
|
class CRLProviderInterface:
|
|
def sync_crls(self): # pragma: no cover
|
|
"""
|
|
Retrieve copies of the CRLs and unpack them to disk.
|
|
"""
|
|
raise NotImplementedError()
|
|
|
|
|
|
class RackspaceCRLProvider(CRLProviderInterface):
|
|
def __init__(self, app):
|
|
provider = app.config.get("CRL_STORAGE_PROVIDER") or app.config.get(
|
|
"STORAGE_PROVIDER"
|
|
)
|
|
self.container = get_rackspace_container(
|
|
provider=provider,
|
|
container=app.config.get("CRL_STORAGE_CONTAINER"),
|
|
key=app.config.get("STORAGE_KEY"),
|
|
secret=app.config.get("STORAGE_SECRET"),
|
|
region=app.config.get("CRL_STORAGE_REGION"),
|
|
)
|
|
self._crl_dir = app.config.get("CRL_STORAGE_CONTAINER")
|
|
self._object_name = app.config.get("STORAGE_CRL_ARCHIVE_NAME")
|
|
self._object = None
|
|
|
|
@property
|
|
def object(self):
|
|
if self._object is None:
|
|
self._object = self.container.get_object(object_name=self._object_name)
|
|
|
|
return self._object
|
|
|
|
def sync_crls(self):
|
|
if not os.path.exists(self._crl_dir):
|
|
os.mkdir(self._crl_dir)
|
|
|
|
with TemporaryDirectory() as tempdir:
|
|
dl_path = os.path.join(tempdir, self._object_name)
|
|
success = self.object.download(dl_path, overwrite_existing=True)
|
|
if not success:
|
|
raise CSPFileError("The CRL package was not downloaded")
|
|
archive = tarfile.open(dl_path, "r:bz2")
|
|
archive.extractall(self._crl_dir)
|