I have a custom middleware in Django to force all the requests to go through a login authentication (with few exceptions like api/token
).
This project allows users to authenticate either via a JWT token or a login in
/admin/login
and all unauthenticated users are redirected to /admin/login.
for authentication.
We deployed the project in Kubernetes and we want Prometheus to scrape /metrics
endpoint but we don't want it to be exposed to unauthenticated users. Prometheus allows for authentication with username
and password
. The thing is that when a request is sent to /metrics
, because of the middleware, the request is redirected to /admin/login
.
So I believe I need to write a custom authentication backend specifically designed for the metrics
endpoint and place it before the other authentication methods.
The request always goes through the middleware first so it will always be redirected to /admin/login
and then will go through the authentication backend.
What is the right way of doing this?
- middleware.py
class LoginRequiredMiddleware(MiddlewareMixin):
def __init__(self, get_response):
self.get_response = get_response
def process_request(self, request):
assert hasattr(request, 'user')
path = request.path_info.lstrip('/')
if path == '' or path == '/':
return self.get_response(request)
url_is_exempt = any(url.match(path) for url in EXEMPT_URLS)
if request.user.is_authenticated or url_is_exempt:
# If the user is authenticated OR the URL is in the exempt list
# go to the requested page
return self.get_response(request)
else:
# Trying to access any page as a non authenticated user
return redirect(f"{settings.LOGIN_URL}?next=/{path}")
- backends.py
class MetricsAuthBackend(BaseBackend):
def authenticate(self, request, username=None, password=None):
if '/metrics' in request.path:
if username == "username":
#need to fix this to use the hash of the password
pwd_valid = check_password(password, "password")
if pwd_valid:
user = User.objects.get(username=username)
return user
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None