Last active
July 16, 2020 09:28
-
-
Save magzim21/78df23de1b42d95fd0441e5552e3051e to your computer and use it in GitHub Desktop.
It scans nginx.conf with included configs and outputs (creates redirects.csv) all redirects in a short, handy form.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import crossplane, re, csv | |
| # !!! CHANGE include /opt/nginx/conf/conf.d/*.conf; . /conf.d/*.conf; | |
| payload = crossplane.parse('nginx.conf') | |
| # In order to understand structure go to https://codebeautify.org/python-formatter-beautifier and paste result of print(payload['config']) | |
| # print(payload['config']) | |
| # print(payload) | |
| files = payload['config'] | |
| # FINDING ALL UPSTREAMS | |
| upstreams ={} # | |
| for file in files: # ITERATING THROUGH EACH FILE | |
| # print(file['file']) # config file path | |
| # servers = [] # how did I want to use it? | |
| for directive1 in file['parsed']: # ITERATING THROUGH FILE LINES | |
| if directive1['directive'] == 'upstream': # UPSTREAM CONTEXT | |
| upstream = directive1 | |
| upstream_name = upstream["args"][0] | |
| upstreams[upstream_name] = [] | |
| # print(f'upstream {upstream_name}') | |
| # breakpoint() | |
| for directive2 in upstream["block"]: | |
| if directive2['directive'] == 'server': | |
| server = directive2 | |
| server_addr = server["args"][0] | |
| # servers.append(server_addr) | |
| upstreams[upstream_name].append(server_addr) | |
| # print(f'server {server_addr}') | |
| with open('redirects.csv', 'w', newline='') as csvfile: | |
| fieldnames = ['FROM', 'WHERE'] | |
| csv.register_dialect("tabs",delimiter=",") | |
| writer = csv.DictWriter(csvfile, fieldnames=fieldnames, dialect='tabs' ) | |
| writer.writeheader() | |
| for file in files: # ITERATING THROUGH EACH FILE | |
| # UNCOMMENT TO FIND LINES OF EACH CONFIG | |
| # print(file['file']) # config file path | |
| # if file['file'] == "./conf.d/6056.qbreport.conf": DEBUGGINNG | |
| # breakpoint() | |
| writer.writerow({'FROM': 'config file: ' + file['file'], 'WHERE': '-------------'}) | |
| # DEBUGGING BLOCK | |
| # if file['file'] == '././conf.d/zabbix.minfin.local.conf': | |
| # breakpoint() | |
| for directive1 in file['parsed']: # ITERATING | |
| # THROUGH FILE LINES | |
| if directive1['directive'] == 'server': # SERVER CONTEXT | |
| server=directive1 | |
| for directive2 in server['block']: | |
| if directive2['directive'] == 'listen': | |
| listen = directive2["args"][0] | |
| # print(f'listen on {listen}') # listen on | |
| if directive2['directive'] == 'location': | |
| location = directive2["args"] | |
| # print(f'location: {location}') # location specified | |
| for directive3 in directive2['block']: | |
| if directive3['directive'] == 'proxy_pass': | |
| where = directive3["args"][0] | |
| # regex to find ip in a proxy pass (?<=http://)[\d|\.|:]+ | |
| # regex to find upstream in a proxy pass (?<=http://)[a-zA-Z_-]+ | |
| # print(f'proxy_pass {proxy_pass}') # proxy pass | |
| regex=r'(?<=://)[^/:]+' # !!! WORKS WITH HTTP ONLY !!! | |
| if 'https://' in where: | |
| print('UPSTREAM CONTAINS HTTPS! REFACTOR YOUR CODE.', file['file']) | |
| # breakpoint() | |
| # exit(1) | |
| # print(proxy_pass) | |
| # breakpoint() | |
| matches = re.findall(regex, where, re.DOTALL) | |
| # print(upstreams) | |
| if matches and matches[0] in upstreams: # in case upstream name is present in a proxy pass | |
| # .join may result few servers to pe printed in one line, if there are few servers in a upstream | |
| # print(" ".join(upstreams[matches[0]])) | |
| # print(file['file']) | |
| where = re.sub(regex, " ".join(upstreams[matches[0]]), where, 0, re.MULTILINE) # " ".join(upstreams[matches[0]]) is a list of upstream's servers | |
| elif directive3['directive'] == 'fastcgi_pass': | |
| where = directive3["args"][0] | |
| # breakpoint() | |
| elif directive3['directive'] == 'root': | |
| where = directive3["args"][0] | |
| # breakpoint() | |
| try: | |
| # .join may result few location args to pe printed in one line, if there are few arags e.g " = / " | |
| map = f'{listen}{" ".join(location)} -> {where}' | |
| writer.writerow({'FROM': listen + " ".join(location), 'WHERE': where}) | |
| # print(map) | |
| del where | |
| except NameError: | |
| # IF "proxy_pass" , "root", "fastcgi_pass" were not found in "location" it will be skipped | |
| # IF configuration is not based on location context - this script will pass it | |
| pass | |
| # print('\n') | |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
README
This is a handy script to parse large nginx config.
This script scans nginx config (as well as "include" statements) and saves the output in a human readable text file 'redirects.csv'
The format is :
Dependencies: crossplane