I'm running a Django website and using lets encrypt for my SSL. Configuration of the framework is such that I can't allow access on: http://url.com/.xxxx
What I can allow free access to is:
http://url.com/static/.xxxx
My /static/ URL can accept and host any random files lets encrypt needs. Is there a way to have certbot support /static/ instead of just using / for the URL?
Thanks
EDIT
I've found a work around that is acceptable for me. Further digging, I found that /.well-known/ is always the base directory for SSL checking. That means we can add a static directory which will work nicely with certbot. Here's how, firstly add this into your apache config:
Alias /.well-known/ /var/www/XXXXX/website/static/.well-known/
<Directory /var/www/XXXXX/website/static/.well-known/>
Require all granted
</Directory>
Then add this into your settings.py file:
STATIC_ENCRYPT_URL = '/.well-known/'
STATIC_ENCRYPT_ROOT = '/var/www/XXXXX/website/static/'
Add this into your urls.py:
urlpatterns = [
...
] + static(settings.STATIC_ENCRYPT_URL, document_root=settings.STATIC_ENCRYPT_ROOT)
Reset your webserver. Now you have a special url /.well-known/ which will host any file certbot requires.
I'd still like a better answer than this.
In case other users come this way like I did from Google, here's how I improved this situation:
I was unsatisfied by my options when it came to creating ACME challenges for Let's Encrypt when running a Django application. So, I rolled my own solution and created a Django app! Basically, you can manage your ACME challenges as just another object, and the app will produce the proper end-point URL.
Simply pip install django-letsencrypt and follow the README to be on your way.
Related
EDIT: The reason of my problem is mod_userdir. So if your host has enabled mod_userdir like Hostgator reseller package for example http://support.hostgator.com/articles/specialized-help/technical/apache-htaccess/mod_userdir then be sure that you host can disable this. Apparently Hostgator refused to disable this for the specific hosting package
Recently I received a phishing warning from google related to a file that doesn't exist in my server. The reason that it appears as it is hosted on my server is because I'm on a shared/reseller Apache hosting package. So I discovered that I can access any file of another website which is hosted on the same server as my site if I know the username of the owner of the website.
Meaning I can access
http://mywebsite.com/~somebodyelsesusername/any_path_to_their_files.php
Well this behavior is undesirable, so I want to deny access to other's websites through my domain using .htaccess
How can I block every root folder for instance mydomain.com/~somefolder/ starting with ~ without knowing what follows next? Of course I have to block access to any files or folders of that folder. I tried
<DirectoryMatch "^\~|\/\~">
Order allow,deny
Deny from all
</DirectoryMatch>
But I guess I'm not doing it right.
The answer below answers in fact the question however it doesn't fix my problem due to special circumstances. So I marked it as correct and I will further investigate the issue
<DirectoryMatch> can only be used in the server configuration file, or virtual host context, not through .htaccess.
You can possibly block access using mod_rewrite. Make sure the module is enabled, then use the following directives:
RewriteEngine on
RewriteRule ^~ - [F,L]
I have hosted to django admin project on a local machine X.
http://10.4.x.y/myapp/admin works.
I have an external IP on another machine Y and i am doing a proxy pass
from the Y to X.
http://proxypassname.com/myapp/admin works.
But, When i click the link "Save" or "Save continue editing" button after editing in admin page, it redirects to local machine ip (i.e. http://10.4.x.y/myapp/blah_blah_blah).
How to make sure that the django project redirects to proxypass name instead of local IP?
This is happening because the admin redirects to IP it thinks it has. It gets in in the HTTP request's header.
However, the fix is very easy. Assuming you proxy server implements the X-Forwarded-For standard, it could be easily fixed.
in your settings.py, simply set:
USE_X_FORWARDED_HOST = True
and restart your Django.
If that doesn't work, you can try to see if your proxy sets a different kind of header, and write a middleware that does the same thing. It's the first example on Django's documentation chapter on middleware
I did these two things and it worked.
Whenever you add a ProxyPass, you should add ProxyPassReverse
SITE_ID should be set to the domain where you want to point this django project.
I'm using mod_wsgi with a url prefix. my setup is:
Alias /prefix /path_to_wsgi_file/file.wsgi
<Directory /path_to_wsgi_file>
Options ExecCGI
SetHandler wsgi-script
...
</Directory>
I would like my django tests to simulate this situation so I could avoid differences between the testing and real env. That means I want request.get_full_path() to contain the /prefix
Any way to do that?
EDIT: after going through the source to understand what FORCE_SCRIPT_NAME does, looks like it's used when wsgi.py calls set_script_prefix() of urlresolvers.
My problem is that this isn't called when I run "manage.py test".
I guess I could call this method myself in the test.
Any better suggestions?
Usually, you'll have the SCRIPT_NAME properly configured on the Web server and let reverse handle everything for you. If you want to configure a particular prefix to be applied, you can configure FORCE_SCRIPT_NAME, which will override any particular SCRIPT_NAME that may be configured or not.
This will allow you to reverse and serve URLs on a given /prefix.
I'm trying to get the client's certificate and sign an xml file using it.
I have added the following to my virtual hosts:
SSLVerifyClient optional
SSLVerifyDepth 1
SSLOptions +stdEnvVars
This should allow mod_ssl to get the user's certificate. But I don't know how to pass it along to my django app. Any help is appreciated. Thanks.
You should use
SSLOptions +StdEnvVars
SSLOptions +ExportCertData
in apache config to have SSL_CLIENT_CERT in the environment.
With flask, it will be in request.environ['SSL_CLIENT_CERT']
Based on the discusson of the other answer, it might be request.META['SSL_CLIENT_CERT'] for django.
Those Apache configuration directives mean that mod_ssl environment variables should now be available in the environment inherited by Django. You can therefore access them using the os.environ object in your Django view:
import os
client_cert = os.environ['SSL_CLIENT_CERT']
The SSL_CLIENT_CERT variable contains the PEM-encoded client certificate.
SSLOptions +StdEnvVars +ExportCertData
SSL_CLIENT_CERT will contain the PEM encoded certificate.
SSL_CLIENT_CERT_CHAIN_n (where n is a number) and SSL_SERVER_CERT are also included, but probably uninteresting.
It's a pity that one can't configure exactly which items you want added to the environment. It would be much more svelte having only what's needed (for me common name and that the verify succeeded - though that may be implied with verify required, and for you the client cert PEM).
I have a django web application that's running on apache 2.2.14 and I want to run the admin application over https.
Having read considerable discussions on using a proxy, writing middleware, running alternative wsgi scripts, the chaps in #httpd came to my rescue. The solution is so simple, I was surprised I didn't find it online, so I'm curious to see if I've made some glaring assumptions or errors.
One complication was that I also wanted to run one of my django apps in the site over https, that is everything on /checkout.
Essentially, if a user requests a URI starting with /admin or /checkout on http, they are to be redirected to that URI but on https. Conversely, if a user requests a URI that does not start with /admin or /checkout on https, they are to be redirected to that URI but on http.
The key to solving this problem was to use Redirect and RedirectMatch directives in my VirtualHost configuration.
<VirtualHost *:80>
... host config stuff ...
Redirect /admin https://www.mywebsite.com/admin
Redirect /checkout https://www.mywebsite.com/checkout
</VirtualHost>
<VirtualHost *:443>
... ssl host config stuff ...
RedirectMatch ^(/(?!admin|checkout).*) http://www.mywebsite.com$1
</VirtualHost>
Another approach is to use #secure_required decorator. This will automatically rewrite the requested url and redirect to https://... version of the URL. Then you don't have to have Redirect in *:80 configuration. *:443 configuration may still be required for performance purpose if you want other traffic to go through normal http traffic.
I tried your solution, but ran into several problems. First, the formatting on the admin site disappeared, as if it could not find the admin static files. Second, if I tried to reach the non-admin site through https, the browser would not find it and redirect me to Yahoo search. Oddly, if I edited the yahoo search URL to eliminate all text except my correct URL (minus the http://), it would continue to search through yahoo for my site. However, typing the exact same URL afresh sent me to my site.
I solved all of these issues by simply removing the
RedirectMatch ^(/(?!admin|checkout).*) http://www.mywebsite.com$1
directive.
I should mention that I don't have a /checkout section on my site and am only trying to secure /admin. ... and yes, I did substitute my URL for "mywebsite.com"
What you described should work, but there may be a problem in the future if you need to make changes to which paths are/are not HTTPS. Because this method requires the ability to correctly modify the Apache config file it means you do not want novices in the loop. Screw up the config file and your site can go 500-error in the blink of an eye.
We chose to have a simple text file that had a list of the must-be-HTTPS paths. Anyone on the project can edit it and it is checked for correctness when it is loaded. We handle any needed redirects to/from HTTPS in middleware and it seems to work just fine. This method will also work if you are running anything other than Apache.