简体   繁体   English

拒绝访问在 S3 AWS 存储桶上公开的 css 文件

[英]Access denied to css file that is public on S3 AWS bucket

So I have a Django application running on a docker container, on AWS EC2.所以我有一个 Django 应用程序在 AWS EC2 上的 docker 容器上运行。 The static content is hosted on an S3 bucket (css, javascript, etc.). static 内容托管在 S3 存储桶上(css、javascript 等)。 This all works fine.这一切都很好。

I did implement a PDF output for some files using weasy print.我确实使用 weasy print 为某些文件实现了 PDF output 。 Locally, it produces the expected PDF fine.在本地,它会产生预期的 PDF 罚款。 However on the server, I get a 500 error.但是在服务器上,我收到 500 错误。 Upon closer inspection, the following error popped in the django logs that I have added to my decorator (that is responsible for generating the PDF).仔细检查后,我添加到我的装饰器(负责生成 PDF)的 django 日志中弹出以下错误。 The decorator decorates some handle that is called, and the produced PDF shows up in the download folder.装饰器装饰了一些被调用的句柄,生成的 PDF 出现在下载文件夹中。

A decorated handler:装饰处理程序:

@generate_pdf_httpresponse
def handler_warehouse_packingslip(request, **kwargs):
    id = kwargs.get("pk")                                   
    context = { .... details to provide to print.... }
    filename = "foo.pdf"
    infos = {"context":context, "template_path":'projectlibs/pdf_outputs/pdf_base.html', "extra_css_files":[], "filename":filename,"request":request}
    return infos

The decorator:装饰师:

def generate_pdf_httpresponse(func):
    @functools.wraps(func)
    def wrapper_generate_pdf_httpresponse(*args, **kwargs):

        try:
            logger.info(f"Wrapper for pdf response")
            value = func(*args, **kwargs)
            html_string = render_to_string(value.get("template_path"), context=value["context"])
            html = HTML(string=html_string, base_url=value["request"].build_absolute_uri())
            css_files = []
            pdf = html.write_pdf(stylesheets=css_files)
            logger.info(f"Creating tmp file for pdf response")
            with tempfile.NamedTemporaryFile() as file:
                file.write(pdf)
                file.seek(0)
                stream = file.read()
            httpresponse = HttpResponse(content_type='application/pdf;', content=stream)
            httpresponse['Content-Disposition'] = f'attachment; filename={value["filename"]}'
            httpresponse['Content-Transfer-Encoding'] = 'binary'
            return httpresponse
        except Exception as ex:
            logger.error(f"PDF wrapper failed: {ex}")
    return wrapper_generate_pdf_httpresponse

Which yields this error (on aws):这会产生此错误(在 aws 上):

27/12/21 14:03:43 INFO DEFAULT: Wrapper for pdf response
27/12/21 14:03:43 INFO DEFAULT: Request to print packing skips warehouse.... 
27/12/21 14:03:43 ERROR DEFAULT: PDF wrapper failed: Attempted access to '/css/pdf2.css' denied.

But that file is public - I can access it directly from a web (https://<my_s3_bucketname>.s3.amazonaws.com/static/css/pdf2.css).但该文件是公开的 - 我可以直接从 web (https://<my_s3_bucketname>.s3.amazonaws.com/static/css/pdf2.css) 访问它。 The main stylesheet I use is also available there, referenced by the same tags & works fine.我使用的主要样式表也在那里可用,由相同的标签引用并且工作正常。

Eg this works fine:例如,这很好用:

<link rel="stylesheet" type="text/css" href="{% static 'css/mystyle.css' %}">

But not this:但不是这个:

<link href="{% static '/css/pdf2.css'  %}" rel="stylesheet" type="text/css" >

So.... where/how should I troubleshoot this?所以....我应该在哪里/如何解决这个问题?

Checked:检查:

  • pdf2.css exists under the static s3 bucket (and it's an access denied, not a not found) pdf2.css 存在于 static s3 存储桶下(这是访问被拒绝,而不是未找到)
  • if I change the css file referenced from the template (that is used to create the pdf), then I also get denied.如果我更改从模板引用的 css 文件(用于创建 pdf),那么我也会被拒绝。 So it seems that my application trying to reach the css from the decorator is what causes the issue, somehow.所以似乎我的应用程序试图从装饰器到达 css 是导致问题的原因,不知何故。

So, I haven't managed to find an actual answer to the initial question (someone wrote a comment to the effect that the css files wasn't served from the S3 bucket in the pdf case, but I didn't fully understand what he meant and he deleted the comment).所以,我还没有设法找到最初问题的实际答案(有人写了一条评论,大意是 pdf 案例中的 S3 存储桶中没有提供 css 文件,但我不完全理解他的意思意思是,他删除了评论)。

However, one change that does work is to replace the in-template css link, and shifting that to weasy-print.但是,一项有效的更改是替换模板内的 css 链接,并将其转移到 weasy-print。 From the code above:从上面的代码:

from django.conf import settings
css_files =  [ f"{settings.STATICFILES_DIRS[0]}/css/pdf2.css"]

assuming properly set STATICFILES_DIRS in settings.py假设在 settings.py 中正确设置了 STATICFILES_DIRS

Then remove the <link href="{% static '/css/pdf2.css' %}" rel="stylesheet" type="text/css" > .然后删除<link href="{% static '/css/pdf2.css' %}" rel="stylesheet" type="text/css" >

Then, since weasy print fetches the actual file locally (eg from the EC2 instance, under its static folder), then it works.然后,由于 weasy print 在本地获取实际文件(例如,从 EC2 实例,在其 static 文件夹下),因此它可以工作。 I guess since that's also committed to git from the same pipeline (eg collecstatic etc.), it's a decent solution from a devops perspective, doesn't require special cases steps/configs.我想因为这也致力于 git 从同一管道(例如集体等),从 devops 的角度来看,这是一个不错的解决方案,不需要特殊情况的步骤/配置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM