Can you disable wagtail admin url? - wagtail

Is it possible to completely disable url login of wagtail admin on production. as i want to setup a replicated environment in a Bastian box so i only allow my ip address when im making changes

Have you tried removing the admin urls from your url config?
# urls.py
urlpatterns = [
# uncomment the following line
# url(r'^admin/', include(wagtailadmin_urls)),
url(r'^documents/', include(wagtaildocs_urls)),
# For anything not caught by a more specific rule above, hand over to
# Wagtail's page serving mechanism. This should be the last pattern in
# the list:
url(r'', include(wagtail_urls)),
# Alternatively, if you want Wagtail pages to be served from a subpath
# of your site, rather than the site root:
# url(r'^pages/', include(wagtail_urls)),
]

You can blocking/allowing IP-addresses in Nginx
location /admin/ {
allow XXX.XX.XX.XX; ## Your specific IP
deny all;
}

#user8585282: If you're trying to filter URIs in Nginx, you can do so by editing the Nginx config file for you site (in Ubuntu it's at /etc/nginx/sites-enabled/my-project).
Then, in the server block, add the following code (you can use IPv4 and IPv6 with CIDR).
server {
...
#restricts wagtail admin to this IP CIDR Block
location = /admin {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
allow XX.XX.XX.XX/24;
deny all;
}
#restricts django admin to this IP CIDR Block
location = /django-admin {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
allow XX.XX.XX.XX/24;
deny all;
}
...
}

Related

Cloud Storage Signed URLs By Proxy

I'm trying to support large file uploads for a Cloud Run (and App Engine) project. There are some constraints that prevent the usual workarounds from working:
The clients are .NET 4.0 applications which means HTTP2 is not available (which gets you around at least Cloud Run's 32MB request size limit)
Legacy clients are not upgradable so chunked uploads are not available for them, and backwards compatibility is a requirement
Signed URLs to cloud storage is the current solution and work well, however some % of clients do not work at all because the customer's IT has blocked googleapis (but not our company domain)
Asking the customer's IT to unblock googleapis is difficult/non-starter
This leads me to the conclusion that I should setup a forward proxy that allows Signed URLs to get around IT restrictions through our GCP project/company domain. I would accomplish this in Compute Engine with an instance running nginx or squid or something and then have a load balancer direct URLs of a certain pattern to the forward proxy which will rewrite the URL to the correct cloud storage signed URL and forward the request.
However, this seems like a bit of a clunky solution. Is there something simpler native to GCP that accomplish what I'm trying to do?
I was able to proxy cloud storage signed URLs using nginx:
events {
worker_connections 1024;
}
http {
client_max_body_size 500M;
server {
listen 80;
listen [::]:80;
server_name mydomain;
location /storagepxy/ {
proxy_pass https://storage.googleapis.com/;
}
}
}
I then setup a GCP load balancer to direct any requests starting with /storagepxy/* to a compute engine instance group running nginx with the above config.
Thus, I could read/write to cloud storage using requests of the form:
GET mydomain/storagepxy/[cloud storage signeduri]
PUT mydomain/storagepxy/[cloud storage signeduri]
So if you had a signed URL like:
https://storage.googleapis.com/example-bucket/cat.jpeg?X-Goog-Algorithm=
GOOG4-RSA-SHA256&X-Goog-Credential=example%40example-project.iam.gserviceaccount
.com%2F20181026%2Fus-central1%2Fstorage%2Fgoog4_request&X-Goog-Date=20181026T18
1309Z&X-Goog-Expires=900&X-Goog-SignedHeaders=host&X-Goog-Signature=247a2aa45f16
9edf4d187d54e7cc46e4731b1e6273242c4f4c39a1d2507a0e58706e25e3a85a7dbb891d62afa849
6def8e260c1db863d9ace85ff0a184b894b117fe46d1225c82f2aa19efd52cf21d3e2022b3b868dc
c1aca2741951ed5bf3bb25a34f5e9316a2841e8ff4c530b22ceaa1c5ce09c7cbb5732631510c2058
0e61723f5594de3aea497f195456a2ff2bdd0d13bad47289d8611b6f9cfeef0c46c91a455b94e90a
66924f722292d21e24d31dcfb38ce0c0f353ffa5a9756fc2a9f2b40bc2113206a81e324fc4fd6823
a29163fa845c8ae7eca1fcf6e5bb48b3200983c56c5ca81fffb151cca7402beddfc4a76b13344703
2ea7abedc098d2eb14a7
You could proxy it via:
https://mydomain/storagepxy/example-bucket/cat.jpeg?X-Goog-Algorithm=
GOOG4-RSA-SHA256&X-Goog-Credential=example%40example-project.iam.gserviceaccount
.com%2F20181026%2Fus-central1%2Fstorage%2Fgoog4_request&X-Goog-Date=20181026T18
1309Z&X-Goog-Expires=900&X-Goog-SignedHeaders=host&X-Goog-Signature=247a2aa45f16
9edf4d187d54e7cc46e4731b1e6273242c4f4c39a1d2507a0e58706e25e3a85a7dbb891d62afa849
6def8e260c1db863d9ace85ff0a184b894b117fe46d1225c82f2aa19efd52cf21d3e2022b3b868dc
c1aca2741951ed5bf3bb25a34f5e9316a2841e8ff4c530b22ceaa1c5ce09c7cbb5732631510c2058
0e61723f5594de3aea497f195456a2ff2bdd0d13bad47289d8611b6f9cfeef0c46c91a455b94e90a
66924f722292d21e24d31dcfb38ce0c0f353ffa5a9756fc2a9f2b40bc2113206a81e324fc4fd6823
a29163fa845c8ae7eca1fcf6e5bb48b3200983c56c5ca81fffb151cca7402beddfc4a76b13344703
2ea7abedc098d2eb14a7
Note: If your bucket path contains URL-encoded characters such as colons, you'll need a slightly more complicated nginx config:
# This is a simple nginx configuration file that will proxy URLs of the form:
# https://mydomain/storagepxy/[signed uri]
# to
# https://storage.googleapis.com/[signed uri]
#
# For use in GCP, you'll likely need to create an instance group in compute engine running nginx with this config
# and then hook up a load balancer to forward requests starting with /storagepxy to it
worker_processes auto; # Auto should spawn 1 worker per core
events {}
http {
client_max_body_size 500M;
server {
listen 80; # IPv4
listen [::]:80; # IPv6
server_name mydomain;
location /storagepxy/ {
# To resolve storage.googleapis.com
resolver 8.8.8.8;
# We have to do it this way in case filenames have URL-encoded characters in them
# See: https://stackoverflow.com/a/37584637
# Also note, if the URL does not match the rewrite rules then return 400
rewrite ^ $request_uri;
rewrite ^/storagepxy/(.*) $1 break;
return 400;
proxy_pass https://storage.googleapis.com/$uri;
}
}
}

Hosting Docusaurus v2 using Nginx

I'm attempting to use nginx as the reverse proxy to host Docusaurus v2 on Google AppEngine.
GooglAppEngine has HTTPS turned on. And Nginx listens on port 8080. Hence by default all requests are over HTTPS and the connections managed by Google AppEngine.
However, I'm having an issue when users perform the following actions :
Reach the landing page
Go to documentations (any page).
Refresh the page.
The user is getting directed to port 8080 and not the https site of docusaurus.
Without refreshing the page, the user is able to successfully navigate the site. It's when the user hits a refresh button that they get the redirect. Looking at the header information, I see the response pointing them to port 8080 but I'm not sure why that is happening.
Wondering if anyone has successfully been able to set up Docusaurus v2 with nginx ?
My config for nginx is as follow :
events {
worker_connections 768;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logs will appear on the Google Developer's Console when logged to this
# directory.
access_log /var/log/app_engine/app.log;
error_log /var/log/app_engine/app.log;
gzip on;
gzip_disable "msie6";
server {
# Google App Engine expects the runtime to serve HTTP traffic from
# port 8080.
listen 8080;
root /usr/share/nginx/www;
index index.html index.htm;
location / {
if ($http_x_forwarded_proto = "http") {
return 301 https://$server_name$request_uri;
}
}
}
This is probably due to the docusaurus website linking to directories without trailing slash /, causing a redirect which is setup to include the port by default.
Looking into the docusaurus build directory you will see that your pages are defined as folders containing index.html files. Without the / the server needs to redirect you to {page}/index.html.
Try to call the URL with / and no port, which should be successful:
https://{host}/docs/{page}/
Therefore fixing the problem, you could try to change the redirect rules to not include the port with the port_in_redirect parameter:
server {
listen 8080;
port_in_redirect off;
# More configuration
...
}
See the documentation for more details.

Can a ReactJS app with a router be hosted on S3 and fronted by an nginx proxy?

I may be twisting things about horribly, but... I was given a ReactJS application that has to be served out to multiple sub-domains, so
a.foo.bar
b.foo.bar
c.foo.bar
...
Each of these should point to a different instance of the application, but I don't want to run npm start for each one - that would be a crazy amount of server resources.
So I went to host these on S3. I have a bucket foo.bar and then directories under that for a b c... and set that bucket up to serve static web sites. So far so good - if I go to https://s3.amazonaws.com/foo.bar/a/ I will get the index page. However most things tend to break from there as there are non-relative links to things like /css/ or /somepath - those break because they aren't smart enough to realize they're being served from /foo.bar/a/. Plus we want a domain slapped on this anyway.
So now I need to map a.foo.bar -> https://s3.amazonaws.com/foo.bar/a/. We aren't hosting our domain with AWS, so I'm not sure if it's possible to front this with CloudFront or similar. Open to a solution along those lines, but I couldn't find it.
Instead, I stood up a simple nginx proxy. I also added in forcing to https and some other things while I had the proxy, something of the form:
server {
listen 443;
server_name foo.bar;
ssl on;
ssl_certificate /etc/pki/tls/certs/server.crt;
ssl_certificate_key /etc/pki/tls/certs/server.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
# Redirect (*).foo.bar to (s3bucket)/(*)
location / {
index index.html index.htm;
set $legit "0";
set $index "";
# First off, we lose the index document functionality of S3 when we
# proxy requests. So we need to add that back on to our rewrites if
# needed. This is a little dangerous, probably should find a better
# way if one exists.
if ($uri ~* "\.foo\.bar$") {
set $index "/index.html";
}
if ($uri ~* "\/$") {
set $index "index.html";
}
# If we're making a request to foo.bar (not a sub-host),
# make the request directly to "production"
if ($host ~* "^foo\.bar") {
set $legit "1";
rewrite /(.*) /foo.bar/production/$1$index break;
}
# Otherwise, take the sub-host from the request and use that for the
# redirect path
if ($host ~* "^(.*?)\.foo\.bar") {
set $legit "1";
set $subhost $1;
rewrite /(.*) /foo.bar/$subhost/$1$index break;
}
# Anything else, give them foo.bar
if ($legit = "0") {
return 302 https://foo.bar;
}
# Peform the actual proxy forward
proxy_pass https://s3.amazonaws.com/;
proxy_set_header Host s3.amazonaws.com;
proxy_set_header Referer https://s3.amazonaws.com;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Accept-Encoding "";
proxy_set_header Accept-Language $http_accept_language;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
sub_filter google.com example.com;
sub_filter_once off;
}
}
This works - I go to a.foo.bar, and I get the index page I expect, and clicking around works. However, part of the application also does an OAuth style login, and expects the browser to be redirected back to the page at /reentry?token=foo... The problem is that path only exists as a route in the React app, and that app isn't loaded by a static web server like S3, so you just get a 404 (or 403 because I don't have an error page defined or forwarded yet).
So.... All that for the question...
Can I serve a ReactJS application from a dumb/static server like S3, and have it understand callbacks to it's routes? Keep in mind that the index/error directives in S3 seem to be discarded when fronted with a proxy the way I have above.
OK, there was a lot in my original question, but the core of it really came down to: as a non-UI person, how do I make an OAuth workflow work with a React app? The callback URL in this case is a route, which doesn't exist if you unload the index.html page. If you're going directly against S3, this is solved by directing all errors to index.html, which reloads the routes and the callback works.
When fronted by nginx however, we lose this error->index.html routing. Fortunately, it's a pretty simple thing to add back:
location / {
proxy_intercept_errors on;
error_page 400 403 404 500 =200 /index.html;
Probably don't need all of those status codes - for S3, the big thing is the 403. When you request a page that doesn't exist, it will treat it as though you're trying to browse the bucket, and give you back a 403 forbidden rather than a 404 not found or something like that. So in this case a response from S3 that results in a 403 will get redirected to /index.html, which will recall the routes loaded there and the callback to /callback?token=... will work.
You can use Route53 to buy domain names and then point them toward your S3 bucket and you can do this with as many domains as you like.
You don't strictly speaking need to touch CloudFront but it's recommended as it is a CDN solution which is better for the user experience.
When deploying applications to S3, all you need to keep in mind is that the code you deploy to it is going to run 100% on your user's browser. So no server stuff.

Simple password protection on private next.js site

I am making a next.js app and I've spent hours searching for a very simple way to password protect the app. (It will be used by a small group of friends)
I have tried using Nginx's http auth on my reverse proxy, and that works but it could be annoying to have to sign in all the time as the login doesn't persist long. (Nginx's http auth seems to 'logout' or forget the authorization very quickly)
I also don't want to dive into something as complicated as NextAuth. I don't want user signups, custom views etc, etc.
I just want people to be able to enter one password to view the site. And I would like it to persist on their browser so they wouldn't have to log in all the time with Nginx's http auth.
Is there a way to give users a cookie once they pass the http auth, and then allow them in once they have the cookie?
Can anyone suggest a fairly simple solution? Thanks in advance.
You can do that with the Nginx map directive, which lets you set a variable based upon another variable.
Inside your html block somewhere but outside any server blocks you set up your map directive
map $cookie_trustedclient $mysite_authentication {
default "Your credentials please";
secret-cookie-value off;
}
Whats happening here is Nginx is setting the value of the custom variable $mysite_authentication based upon the value of the cookie named trustedclient.
By default $mysite_authentication will be set to Your credentials please, unless you have a cookie named trustedclient with a value of secret-cookie-value, in which case $mysite_authentication will be set to off
Now within the location block that you have enabled basic auth you change your auth_basic directive to use the new variable, like this:
location /secretfiles {
auth_basic $mysite_authentication;
auth_basic_user_file ....
add_header Set-Cookie "trustedclient=secret-cookie-value;max-age=3153600000;path=/";
}
You can set the cookie here or within your website code. The result being the auth_basic directive gets set to off for people with the right cookie, or the display message for the password box for people without it.
Not super secure, but easy and good enough for most things.
Edit from your config:
# Map block can go here
map $cookie_trustedclient $mysite_authentication {
default "Your credentials please";
secret-cookie-value off;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
# ssl on; # Delete this line, obsolete directive
ssl_certificate /etc/nginx/cloudflare-ssl/certificate.pem;
ssl_certificate_key /etc/nginx/cloudflare-ssl/key.key;
ssl_client_certificate /etc/nginx/cloudflare-ssl/cloudflare.crt;
ssl_verify_client on;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name ********.com;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
# auth_basic "Restricted Content"; # Now this becomes:
auth_basic $mysite_authentication;
auth_basic_user_file /etc/nginx/.htpasswd;
add_header Set-Cookie "trustedclient=secret-cookie-value;max-age=3153600000;path=/";
}
}

Let's Encrypt / Certbot in Google App Engine -> can't check challenge -> Forbidden 403

Using Google App Engine and Let's Encrypt or Certbot, I'm trying to issue a certificate to my web app, but when the challenge is to be tested, the file hosted in /.well-known/acme-challenge/ can't be acessed because (apparently of nginx configuration that prohibits access to dot paths), in other words, it gets a 403 - Forbidden page instead of the key.
I've already tried to change nginx.conf with this:
location ^~ /.well-known/ {
allow all;
}
Restarted nginx service, but still, I can't get it to work.
Did you try using an alias?
location ^~ /.well-known {
allow all;
auth_basic off;
alias /path/to/.well-known/;
}

Resources