Skip to content

Instantly share code, notes, and snippets.

@reactorcoremeltdown
Created March 27, 2020 16:52
Show Gist options
  • Save reactorcoremeltdown/86cbcddf5b532a7b9f768400f401f9d8 to your computer and use it in GitHub Desktop.
Save reactorcoremeltdown/86cbcddf5b532a7b9f768400f401f9d8 to your computer and use it in GitHub Desktop.
{
"host": "127.0.0.1",
"port": 8001,
"userlists": [
"/etc/nginx/httpauth_kibana_ro",
"/etc/nginx/httpauth_kibana_rw"
]
}
#!/usr/bin/env python3
import time
import json
import os
import sys
import base64
import crypt
from http.server import HTTPServer
from http.server import BaseHTTPRequestHandler
def load_config(filename):
with open(filename, 'r') as file:
config = json.load(file)
return config
def parse_users(config):
users = []
for filename in config:
data = open(filename, 'r')
for line in data:
user = line.split(':')
users.append({'username': user[0], 'hashed_password': user[1].split('\n')[0], 'acl': os.path.basename(filename)})
data.close()
return users
class Server(BaseHTTPRequestHandler):
def do_AUTHHEAD(self):
self.send_response(401)
self.send_header('WWW-Authenticate', 'Basic realm="Restricted"')
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
auth_header = self.headers.get('Authorization')
if auth_header == None:
self.do_AUTHHEAD()
self.wfile.write(bytes('No authentication header received', 'utf-8'))
else:
self.respond(auth_header)
def do_POST(self):
auth_header = self.headers.get('Authorization')
if auth_header == None:
self.do_AUTHHEAD()
self.wfile.write(bytes('No authentication header received', 'utf-8'))
else:
self.respond(auth_header)
def handle_http(self, status, content_type, xacl, message):
self.send_response(status)
self.send_header('Content-type', content_type)
self.send_header('XACL', xacl)
self.end_headers()
return bytes(message, "UTF-8")
def respond(self, auth_header):
if self.path == '/auth':
if auth_header == 'None':
response = self.handle_http(401, 'text/html', 'none', 'Authentication failed')
else:
auth_data = auth_header.split(' ')
if auth_data[0] == 'Basic':
credentials = base64.b64decode(auth_data[1]).decode('utf-8').split(':')
matched_entry = {}
for entry in users:
if entry['username'] == credentials[0]:
matched_entry = entry
if matched_entry != {}:
hash_value = matched_entry['hashed_password'].split('$')
encrypted = crypt.crypt(credentials[1], '$' + hash_value[1] + '$' + hash_value[2])
if encrypted == matched_entry['hashed_password']:
print(time.asctime(), 'Authentication succeeded for user %s from ACL %s' % (matched_entry['username'], matched_entry['acl']))
response = self.handle_http(200, 'text/html', matched_entry['acl'], 'Authentication succeeded')
else:
print(time.asctime(), 'Authentication failed for user %s from ACL %s: password hash mismatch:\n%s != %s' % (matched_entry['username'], matched_entry['acl'], encrypted, matched_entry['hashed_password']))
response = self.handle_http(403, 'text/html', 'none', 'Authentication failed')
else:
response = self.handle_http(403, 'text/html', 'none', 'Authentication failed')
else:
print(time.asctime(), 'User %s not found' % (credentials[0]))
response = self.handle_http(503, 'text/html', 'none', 'Authentication method is not supported')
else:
response = self.handle_http(401, 'text/html', 'none', 'Authentication failed')
self.wfile.write(response)
HOST_NAME = 'localhost'
PORT_NUMBER = 8000
if __name__ == '__main__':
config = load_config(sys.argv[1])
users = parse_users(config['userlists'])
httpd = HTTPServer((config['host'], config['port']), Server)
print(time.asctime(), 'Server UP - %s:%s' % (config['host'], config['port']))
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
httpd.server_close()
print(time.asctime(), 'Server DOWN - %s:%s' % (config['host'], config['port']))
upstream kibana {
server localhost:5601 fail_timeout=10s;
}
upstream kibana_authserver {
server localhost:8001 fail_timeout=10s;
}
upstream httpauth_kibana_rw {
server localhost:8002 fail_timeout=10s;
}
upstream httpauth_kibana_ro {
server localhost:8003 fail_timeout=10s;
}
server {
listen *:82;
server_name kibana.server.tld;
client_max_body_size 8M;
root /srv/www;
access_log /var/log/nginx/kibana.server.tld_access.log json_combined;
error_log /var/log/nginx/kibana.server.tld_error.log;
location = /auth {
internal ;
proxy_pass http://kibana_authserver;
proxy_pass_request_body off;
proxy_pass_request_headers on;
proxy_set_header Content-Length "";
proxy_set_header Host $host;
proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Original-URI $request_uri;
}
location / {
auth_request /auth;
auth_request_set $auth_status $upstream_http_xacl;
proxy_http_version 1.1;
proxy_pass http://$auth_status;
proxy_redirect off;
proxy_set_header Access-Control-Allow-Origin *;
proxy_set_header Connection Keep-Alive;
proxy_set_header Host $host;
proxy_set_header Proxy-Connection Keep-Alive;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen *:8002;
server_name kibana.server.tld;
client_max_body_size 8M;
root /srv/www;
access_log /var/log/nginx/kibana.server.tld_access.log json_combined;
error_log /var/log/nginx/kibana.server.tld_error.log;
location / {
proxy_http_version 1.1;
proxy_pass http://kibana;
proxy_redirect off;
proxy_set_header Access-Control-Allow-Origin *;
proxy_set_header Connection Keep-Alive;
proxy_set_header Host $host;
proxy_set_header Proxy-Connection Keep-Alive;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen *:8003;
server_name kibana.server.tld;
client_max_body_size 8M;
root /srv/www;
access_log /var/log/nginx/kibana.server.tld_access.log json_combined;
error_log /var/log/nginx/kibana.server.tld_error.log;
location / {
proxy_http_version 1.1;
proxy_pass http://kibana;
proxy_redirect off;
proxy_set_header Access-Control-Allow-Origin *;
proxy_set_header Connection Keep-Alive;
proxy_set_header Host $host;
proxy_set_header Proxy-Connection Keep-Alive;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
}
set $posting 11;
if ( $request_method !~ ^(GET|POST|OPTIONS|HEAD)$ ) { return 405; }
if ( $request_method = POST ) { set $posting 1; }
if ( $request_uri ~ ^/(.+)/(_search|_mget|_msearch|_field_stats|_bulk_get|timelion/run)(.*)$ ) { set $posting "${posting}1"; }
if ( $request_method ~ ^(GET|OPTIONS|HEAD)$ ) { set $posting 11; }
if ( $posting != 11 ) { return 403; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment