Skip to content

Instantly share code, notes, and snippets.

@CrackerJackMack
Last active March 10, 2020 07:49
Show Gist options
  • Save CrackerJackMack/8f0e84b2d6ca981f4262b5fa5136375c to your computer and use it in GitHub Desktop.
Save CrackerJackMack/8f0e84b2d6ca981f4262b5fa5136375c to your computer and use it in GitHub Desktop.
worker_processes 5;
events {
}
http {
include /etc/nginx/mime.types;
client_max_body_size 25m;
proxy_read_timeout 300;
proxy_send_timeout 120;
proxy_socket_keepalive on;
proxy_buffers 8 16k; # Buffer pool = 8 buffers of 16k
proxy_buffer_size 16k; # 16k of buffers from pool used for headers
proxy_headers_hash_bucket_size 128;
proxy_headers_hash_max_size 1024;
proxy_http_version 1.1;
map $http_x_forwarded_proto $proxy_forward_scheme {
default $http_x_forwarded_proto;
'' $scheme;
}
server {
listen 7932 default_server;
server_name manage.int.example.com;
location = /healthcheck {
add_header Content-Type text/plain;
return 200 'ok';
}
location = /pingz {
add_header Content-Type text/plain;
return 200 'ok';
}
location = /ping {
add_header Content-Type text/plain;
return 200 'ok';
}
location /oauth2/ {
# oauth2_proxy
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $request_uri;
# or, if you are handling multiple domains:
# proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
}
location = /oauth2/auth {
proxy_pass http://127.0.0.1:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
# nginx auth_request includes headers but not body
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
location / {
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
# pass information via X-User and X-Email headers to backend,
# requires running with -set-xauthrequest flag
auth_request_set $user $upstream_http_x_auth_request_user;
auth_request_set $email $upstream_http_x_auth_request_email;
proxy_set_header X-Forwarded-User $user;
proxy_set_header X-Forwarded-Email $email;
# if you enabled -pass-access-token, this will pass the token to the backend
auth_request_set $token $upstream_http_x_auth_request_access_token;
proxy_set_header X-Access-Token $token;
# if you enabled --cookie-refresh, this is needed for it to work with auth_request
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
# When using the -set-authorization-header flag, some provider's cookies can exceed the 4kb
# limit and so the OAuth2 Proxy splits these into multiple parts.
# Nginx normally only copies the first `Set-Cookie` header from the auth_request to the response,
# so if your cookies are larger than 4kb, you will need to extract additional cookies manually.
auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1;
# Extract the Cookie attributes from the first Set-Cookie header and append them
# to the second part ($upstream_cookie_* variables only contain the raw cookie content)
if ($auth_cookie ~* "(; .*)") {
set $auth_cookie_name_0 $auth_cookie;
set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1";
}
# Send both Set-Cookie headers now if there was a second part
if ($auth_cookie_name_upstream_1) {
add_header Set-Cookie $auth_cookie_name_0;
add_header Set-Cookie $auth_cookie_name_1;
}
# nest location block so we get all the same auth protections
location /static/ {
alias /static/;
}
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $proxy_forward_scheme;
proxy_set_header X-Forwarded-User $http_x_forwarded_user;
proxy_set_header X-CSRFToken $http_x_csrftoken;
# gunicorn
proxy_pass http://127.0.0.1:8001;
}
}
}
diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py
index 6c33e5b5..68f0a2df 100644
--- a/netbox/netbox/settings.py
+++ b/netbox/netbox/settings.py
@@ -12,7 +12,7 @@ from django.core.exceptions import ImproperlyConfigured
# Environment setup
#
-VERSION = '2.7.7'
+VERSION = '2.7.7-pf1'
# Hostname
HOSTNAME = platform.node()
@@ -101,7 +101,8 @@ SHORT_DATETIME_FORMAT = getattr(configuration, 'SHORT_DATETIME_FORMAT', 'Y-m-d H
SHORT_TIME_FORMAT = getattr(configuration, 'SHORT_TIME_FORMAT', 'H:i:s')
TIME_FORMAT = getattr(configuration, 'TIME_FORMAT', 'g:i a')
TIME_ZONE = getattr(configuration, 'TIME_ZONE', 'UTC')
-
+WEBHOOKS_ENABLED = getattr(configuration, 'WEBHOOKS_ENABLED', False)
+REMOTE_USER_HEADER = getattr(configuration, 'REMOTE_USER_HEADER', None)
#
# Database
@@ -266,6 +267,7 @@ MIDDLEWARE = (
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'utilities.middleware.RemoteUserAuthMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
@@ -404,6 +406,15 @@ if LDAP_CONFIG is not None:
ldap_logger.setLevel(logging.DEBUG)
+#
+# Remote user authentication
+#
+if REMOTE_USER_HEADER:
+ # RemoteUserMiddleware will detect the username in request.META[REMOTE_USER_HEADER]
+ # and will authenticate and auto-login that user using the RemoteUserBackend.
+ AUTHENTICATION_BACKENDS.insert(1, 'utilities.auth_backends.RemoteUserStripEmail')
+
+
#
# Caching
#
diff --git a/netbox/utilities/auth_backends.py b/netbox/utilities/auth_backends.py
index 54541b0b..b236027e 100644
--- a/netbox/utilities/auth_backends.py
+++ b/netbox/utilities/auth_backends.py
@@ -1,5 +1,5 @@
from django.conf import settings
-from django.contrib.auth.backends import ModelBackend
+from django.contrib.auth.backends import ModelBackend, AllowAllUsersRemoteUserBackend
class ViewExemptModelBackend(ModelBackend):
@@ -7,6 +7,7 @@ class ViewExemptModelBackend(ModelBackend):
Custom implementation of Django's stock ModelBackend which allows for the exemption of arbitrary models from view
permission enforcement.
"""
+
def has_perm(self, user_obj, perm, obj=None):
# If this is a view permission, check whether the model has been exempted from enforcement
@@ -15,14 +16,29 @@ class ViewExemptModelBackend(ModelBackend):
action, model = codename.split('_')
if action == 'view':
if (
- # All models are exempt from view permission enforcement
- '*' in settings.EXEMPT_VIEW_PERMISSIONS
+ # All models are exempt from view permission enforcement
+ '*' in settings.EXEMPT_VIEW_PERMISSIONS
) or (
- # This specific model is exempt from view permission enforcement
- '{}.{}'.format(app, model) in settings.EXEMPT_VIEW_PERMISSIONS
- ):
+ # This specific model is exempt from view permission enforcement
+ '{}.{}'.format(
+ app, model) in settings.EXEMPT_VIEW_PERMISSIONS):
return True
except ValueError:
pass
return super().has_perm(user_obj, perm, obj)
+
+
+class RemoteUserStripEmail(AllowAllUsersRemoteUserBackend):
+ def clean_username(self, username):
+ # hook to modify username before user is looked up or created
+ # remove @domain.com from username
+ return username.split('@', 1)[0]
+
+ def configure_user(self, request, user):
+ # hook to modify a new user immediately after it is created
+ # remove '@email.com' from username, and populate user.email
+
+ user.email = "%s@example.com" % user.username
+ user.save()
+ return user
diff --git a/netbox/utilities/middleware.py b/netbox/utilities/middleware.py
index 56477182..516b6a7a 100644
--- a/netbox/utilities/middleware.py
+++ b/netbox/utilities/middleware.py
@@ -4,6 +4,7 @@ from django.conf import settings
from django.db import ProgrammingError
from django.http import Http404, HttpResponseRedirect
from django.urls import reverse
+from django.contrib.auth.middleware import RemoteUserMiddleware
from .views import server_error
@@ -78,3 +79,22 @@ class ExceptionHandlingMiddleware(object):
# Return a custom error message, or fall back to Django's default 500 error handling
if custom_template:
return server_error(request, template_name=custom_template)
+
+
+class RemoteUserAuthMiddleware(RemoteUserMiddleware):
+ """
+ Extension of the RemoteUserMiddleware, if enabled, to allow any authenticated user access to netbox.
+ WARNING. User authorization and access should be handled externally!
+ """
+
+ header = settings.REMOTE_USER_HEADER
+
+ def clean_username(self, username, request):
+ """
+ Perform any cleaning on the "username" prior to using it to get or
+ create the user object. Return the cleaned username.
+ """
+ username = super(RemoteUserAuthMiddleware, self).clean_username(username, request)
+ username = username.split('@', 1)[0]
+ return username
+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment