-
Notifications
You must be signed in to change notification settings - Fork 338
HTTPS Mixed Content for swagger.json with gunicorn #188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The flow between Kubernetes Ingress and your container is HTTP or HTTPS ? |
HTTP. Ingress has the public cert.
Web -> HTTPS -> Ingress -> HTTP -> container
…On Fri, Jul 31, 2020 at 08:53 FLaco ***@***.***> wrote:
The flow between Kubernetes Ingress and your container is HTTP or HTTPS ?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#188 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABO7UUPGXCT5MTPDHLAR2LLR6LLGDANCNFSM4PLFTR5A>
.
|
Are you using ProxyFix as mentioned under Flask Proxy Setups? import logging
from flask import Flask, request, has_request_context
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1)
@app.before_request
def log_request():
app.logger.debug("Request Headers %s", request.headers)
return None
api.init_app(app)
if __name__ == "__main__":
app.run(host='0.0.0.0') This fixed a similar issues I was having with swagger.json mixed content message. |
No, as stated, this is not an issue with werkzueg but with gunicorn as the
problem does not present with uWSGI. But the other issue lies with the fact
that sites should not be using absolute paths with protocols for links to
its ownself. There is no reason for RESTX to render out only swagger.json
with an absolute path while the rest of the static content for the
SwaggerUI is relative.
There should be no need for ProxyFix if relative paths are used as they
should be. Hence the issue and request for a change. Not to mention, you
should never need to do much special at the application side if the reverse
proxy itself is setup correctly, which this one is, because the proxy
should be transparent to the application.
…On Fri, Jul 31, 2020 at 11:40 jhampson-dbre ***@***.***> wrote:
Are you using ProxyFix
<https://werkzeug.palletsprojects.com/en/1.0.x/middleware/proxy_fix/> as
mentioned under Flask Proxy Setups
<https://flask.palletsprojects.com/en/1.1.x/deploying/wsgi-standalone/#proxy-setups>
?
import loggingfrom flask import Flask, request, has_request_contextfrom werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1)
@app.before_requestdef log_request():
app.logger.debug("Request Headers %s", request.headers)
return None
api.init_app(app)
if __name__ == "__main__":
app.run(host='0.0.0.0')
This fixed a similar issues I was having with swagger.json mixed content
message.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#188 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABO7UUM3M37WGKKVLTNTVXLR6L6ZTANCNFSM4PLFTR5A>
.
|
I just ran into the same issue with a very similar setup (Https reverse proxy with SSL termination at Kubernetes ingress). I'm also using Gunicorn and it works fine in combination with ProxyFix. From the Flask docs, I stumbled upon ProxyFix before messing with any Gunicorn config, but I will go back and take a look at them as an alternative. To your point, ProxyFix is a fairly kludgy solution. |
After removing ProxyFix and adding In our case, since the forwarded IP is from the kubernetes ingress, I'm not sure how you could provide the full list of IPs to whitelist more conservatively, but it maybe an acceptable risk if you know that all traffic is coming through the ingress. Using relative path to load swagger.json is still an ideal solution. For a workaround in the middleware layer, both ProxyFix and forwarded_allow_ips have worked as expected in my environment. |
We have just made our own child api class using the RESTX from flask import Blueprint, url_for
from flask_restx import Api
class PatchedApi(Api):
@property
def specs_url(self):
return url_for(self.endpoint('specs'))
api_blueprint = Blueprint('api_v1', __name__, url_prefix='/api/v1')
api = PatchedApi(api_blueprint, title='Test API', version='1.0.0') |
Thanks @jslay88! Just a minor correction: should be |
Hi everyone - just hit this error myself deploying a service to Google Cloud Run using Rest_X - the HTML source is trying to load http not https as required. Reading through comments will a fix be coming for this issue soon or do I need to configure something like ProxyFix or patch the API? |
Sorry, was doing it from memory. |
@dgildeh did you resolve this? Patching the API as jslay88 is trivial, and is what the fix presumably would do anyway. |
Opened a PR to try and get things moving forward. |
Use relative path for `api.specs_url`. Fix #188
No I didn't, I was waiting for an official fix which looks like we have now. I also hit another bug with the default error response not working locally (I don't have the issue to hand but saw several already created for this bug, but creating a default error handler doesn't work, potentially while in Debug mode locally as one issue raised, it renders HTML error instead of the JSON error I'm trying to send for all errors - if I specify an exception class it works as expected thought) And finally I've instrumented OpenTelemetry traces to monitor performance, and seeing a lot of latency before and after my function runs, which may be Flask or I suspect the marshalling of the request/response. Haven't raised a ticket yet as not entirely sure where the latency is coming from yet. With the bugs and latency issues I'm seeing I'm seriously considering moving to FastAPI which I discovered recently, and may be a better fit for my needs. |
Flask incorporates templating and handling of static (although Flask should
not serve static) for frontends.
If all you are trying to accomplish is a RESTful API with a swaggerUI, then
yes, I would highly recommend moving towards FastAPI.
https://github.com/jslay88/fastapi_boilerplate
…On Fri, Sep 4, 2020 at 00:17 David Gildeh ***@***.***> wrote:
Hi everyone - just hit this error myself deploying a service to Google
Cloud Run using Rest_X - the HTML source is trying to load http not https
as required. Reading through comments will a fix be coming for this issue
soon or do I need to configure something like ProxyFix or patch the API?
@dgildeh <https://github.com/dgildeh> did you resolve this? Patching the
API as jslay88 is trivial, and is what the fix presumably would do anyway.
No I didn't, I was waiting for an official fix which looks like we have
now. I also hit another bug with the default error response not working
locally (I don't have the issue to hand but saw several already created for
this bug, but creating a default error handler doesn't work, potentially
while in Debug mode locally as one issue raised, it renders HTML error
instead of the JSON error I'm trying to send for all errors - if I specify
an exception class it works as expected thought)
And finally I've instrumented OpenTelemetry traces to monitor performance,
and seeing a lot of latency before and after my function runs, which may be
Flask or I suspect the marshalling of the request/response. Haven't raised
a ticket yet as not entirely sure where the latency is coming from yet.
With the bugs and latency issues I'm seeing I'm seriously considering
moving to FastAPI which I discovered recently, and may be a better fit for
my needs.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#188 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABO7UUNOVNVKTOU7RIP2V7DSECBALANCNFSM4PLFTR5A>
.
|
Hi @jslay88 ! I am in the exact same situation you mentioned in the issue (kubernetes ingress controller), but I am facing a slightly different (but probably related) problem: If I switch from
This error persists even in HTTP-only access with the latest Have you ever had that issue before? |
@neumannrf you need to install the JS frontend assets for Swagger. The JS packages are in the package.json. You can see an example install command in tasks.py. If the they're installed in the proper location with |
Hi @j5awry! I don't understand what it is I have to do. As you pointed out, all those commands are already incorporated in the |
The issue I was considering is the pathing (and I didn't know your installation method, from source or from pypi). If you're pulling in from source, the assets aren't in the source (which is my guess since you're stating you're pulling from
Compare to installing from Pypi, where we have the assets
So you need to add the assets. You can do this using NPM and package.json in the source code:
|
Make sure that you are also setting gunicorn up correctly as well with --forwarded-allow-ips if deploying with it (you should be). If you are in a kubernetes cluster you can set this to * https://docs.gunicorn.org/en/stable/settings.html#forwarded-allow-ips |
Hi @j5awry ! I don't know why I did not get a notification with your last message. I understand what I have to do now. It is a little bit more complicated to do this inside one of these language-specific cloud buildpacks. Typically, the buildpack that has |
I have noticed that swagger.json fails to load behind an HTTPS proxy (say, a kubernetes ingress controller) when using gunicorn to serve, but not uWSGI. This happens regardless of passing header
X-Forwarded-Proto
as recommended in the gunicorn documentation. While the issue probably lies with gunicorn, I have been able to make a slight change to the library which makes it work with gunicorn and uWSGI.Changing
api.specs_url
to not use_external
onurl_for
, allows it to return just the relative path to swagger.json, instead of a complete URI (/api/v1/swagger.json
vshttp://host.com/api/v1/swagger.json
) and subsequently allows the JS to load swagger.json. This also falls in line with the behavior of other Django REST middlewares, as well as FastAPI.flask-restx/flask_restx/api.py
Line 510 in 66d884f
Repro Steps
Expected Behavior
Ability to load the SwaggerUI from behind an HTTPS reverse proxy using gunicorn. Having the JS load path instead of URI by rendering out api.specs_url not using
_external
. Ergo, a relative path to swagger.json being passed to the swagger-ui template.Actual Behavior
RESTX renders out the entire URI using HTTP (because the connection from proxy to gunicorn is HTTP) for the JS to load swagger.json for the SwaggerUI, thus causing a broken SwaggerUI because its trying to load insecure content on a secure site.
Error Messages/Stack Trace
Environment
Additional Context
Generally, websites use relative paths for their own content.
All of the other static content loaded by the SwaggerUI (CSS, JS bundles, etc) load with relative paths and work. Only swagger.json does not. This is because the
swagger_static
template filter does not use_external
onurl_for
flask-restx/flask_restx/apidoc.py
Line 33 in 66d884f
The text was updated successfully, but these errors were encountered: