diff options
author | Jonas Lindstad <jonaslindstad@gmail.com> | 2015-03-16 23:09:40 +0100 |
---|---|---|
committer | Jonas Lindstad <jonaslindstad@gmail.com> | 2015-03-16 23:09:40 +0100 |
commit | 939b606944b6892d26581bce598c66c790786de9 (patch) | |
tree | 6780dc26bd26c22ca8dce6a7832841b5f4efc37a /fap/httpd | |
parent | 88dfb934e546d02d1f4356032e91277f9f5b94f1 (diff) |
rename + fixes
Diffstat (limited to 'fap/httpd')
-rw-r--r-- | fap/httpd/ex2200.template | 249 | ||||
-rw-r--r-- | fap/httpd/server_http.py | 143 | ||||
-rw-r--r-- | fap/httpd/terminal.log | 14 |
3 files changed, 406 insertions, 0 deletions
diff --git a/fap/httpd/ex2200.template b/fap/httpd/ex2200.template new file mode 100644 index 0000000..aa62ff2 --- /dev/null +++ b/fap/httpd/ex2200.template @@ -0,0 +1,249 @@ +system { + host-name $hostname; + auto-snapshot; + time-zone Europe/Oslo; + authentication-order [ tacplus password ]; + root-authentication { + encrypted-password "$1$v1xWD3zI$OhStP6PnpgIUO3RLtMmIJ/"; + } + name-server { + 1.1.1.1; + 2.2.2.2; + } + login { + user technet{ + uid 2000; + class super-user; + authentication { + encrypted-password "$1$v1xWD3zI$OhStP6PnpgIUO3RLtMmIJ/"; + } + } + } + services { + ssh { + root-login deny; + } + netconf { + ssh; + } + } + syslog { + user * { + any emergency; + } + file messages { + any notice; + authorization info; + } + file interactive-commands { + interactive-commands any; + } + } + ntp { + server 1.2.3.4; + server 2.3.4.5; + } +} + +chassis { + aggregated-devices { + ethernet { + device-count 1; + } + } +} + +interfaces { + interface-range edge-ports { + member-range ge-0/0/0 to ge-0/0/43; + unit 0 { + family ethernet-switching { + port-mode access; + vlan { + members deltagere; + } + } + } + } + interface-range core-ports { + member-range ge-0/0/44 to ge-0/0/47; + ether-options { + 802.3ad ae0; + } + } + ae0 { + description "Til $distro_name $distro_phy_port"; + aggregated-ether-options { + lacp { + active; + } + } + unit 0 { + family ethernet-switching { + port-mode trunk; + vlan { + members deltagere; + } + native-vlan-id mgmt; + } + } + } + vlan { + unit $mgmt_vlan { + description "MGMT L3 interface"; + family inet { + filter { + input v4-mgmt; + } + address $mgmt_addr/$mgmt_cidr; + } + family inet6 { + filter { + input v6-mgmt; + } + } + } + } +} +firewall { + family inet { + filter v4-mgmt { + term accept-noc { + from { + source-address { + 0.0.0.0/0; + } + } + then accept; + } + term accept-icmp { + from { + protocol icmp; + } + then { + accept; + } + } + term reject-all { + then { + log; + syslog; + reject; + } + } + } + } + family inet6 { + filter v6-mgmt { + term accept-noc { + from { + source-address { + ::/0; + } + } + then accept; + } + term accept-icmp { + from { + next-header icmp6; + } + then { + accept; + } + } + term reject-all { + then { + log; + syslog; + reject; + } + } + } + } +} + +ethernet-switching-options { + secure-access-port { + interface edge-ports { + no-dhcp-trusted; + } + vlan deltagere { + arp-inspection; + examine-dhcp; + examine-dhcpv6; + neighbor-discovery-inspection; + ip-source-guard; + ipv6-source-guard; + dhcp-option82; + dhcpv6-option18 { + use-option-82; + } + } + ipv6-source-guard-sessions { + max-number 128; + } + } +} + +protocols { + sflow { + sample-rate { + ingress 10000; + egress 10000; + } + collector 91.209.30.12; + interfaces edge-ports; + interfaces core-ports; + } + igmp-snooping { + vlan all { + version 3; + immediate-leave; + } + } + mld-snooping { + vlan all { + version 2; + immediate-leave; + } + } + rstp { + bridge-priority 8k; + interface edge-ports { + edge; + no-root-port; + } + } + lldp { + interface ae0.0 + } +} + +vlans { + deltagere { + vlan-id $traffic_vlan; + } + mgmt { + vlan-id $mgmt_vlan; + l3-interface vlan.$mgmt_vlan; + } +} + +routing-options { + rib inet.0 { + static { + route 0.0.0.0/0 { + next-hop $mgmt_gw; + } + } + } + rib inet6.0 { + static { + route ::/0 { + next-hop 20a0:dead::beef; + } + } + } +} + + diff --git a/fap/httpd/server_http.py b/fap/httpd/server_http.py new file mode 100644 index 0000000..bc9ceea --- /dev/null +++ b/fap/httpd/server_http.py @@ -0,0 +1,143 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from http.server import BaseHTTPRequestHandler, HTTPServer +from string import Template +import time +import psycopg2 +import psycopg2.extras +import sys +import os + +def main(): + # + # Settings + # + settings = { + 'db': { + 'user': 'bootstrap', + 'password': 'asdf', + 'dbname': 'bootstrap', + 'host': 'localhost' + }, + 'http': { + 'host': '0.0.0.0', + 'port': 80 + } + } + + # + # Connect to DB + # + try: + connect_params = ("dbname='%s' user='%s' host='%s' password='%s'" % (settings['db']['dbname'], settings['db']['user'], settings['db']['host'], settings['db']['password'])) + conn = psycopg2.connect(connect_params) + cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor) + # cur.execute("""SELECT * from switches""") + # rows = cur.fetchall() + # print ("\nSwitches in DB during server_http.py startup:") + # for row in rows: + # print (" --> %s, connected to %s port %s" % (row['hostname'], row['distro_name'], row['distro_phy_port'])) + + except (psycopg2.DatabaseError, psycopg2.OperationalError) as e: + print ('Error: %s' % e) + sys.exit(1) + + except: + print(sys.exc_info()[0]) + sys.exit(1) + + def template_get(model): + return open('fap/httpd/' + model + '.template').read() + + def template_parse(template_src, hostname): + cur.execute("SELECT * FROM switches WHERE hostname = '%s'" % hostname) + if(cur.rowcount == 1): + row = cur.fetchall()[0] + d={ + 'hostname': row['hostname'], + 'distro_name': row['distro_name'], + 'distro_phy_port': row['distro_phy_port'], + 'mgmt_addr': row['mgmt_addr'], + 'mgmt_cidr': row['mgmt_cidr'], + 'mgmt_gw': row['mgmt_gw'], + 'mgmt_vlan': row['mgmt_vlan'], + 'traffic_vlan': row['traffic_vlan'] + } + cur.execute("UPDATE switches SET last_config_fetch = '%s' WHERE hostname = '%s'" % (str(time.time()).split('.')[0], hostname)) # updated DB with last config fetch + conn.commit() + return Template(template_src).safe_substitute(d) + else: + return False + + class httpd(BaseHTTPRequestHandler): + def do_GET(self): + print('[%s] [%s] Incoming HTTP GET URI:%s ' % (self.client_address[0], time.asctime(), self.path)) + + # Client asks for the config file + if '/tg-edge/' in self.path: + hostname = self.path.split('/tg-edge/')[1] + if len(hostname) > 0: + print('[%s] --> Hostname "%s" accepted, fetching info from DB' % (self.client_address[0], hostname)) + template_parsed = template_parse(template_get('ex2200'), hostname) + if template_parsed: + print('[%s] --> Template successfully populated' % self.client_address[0]) + print('[%s] --> Sending response to client' % self.client_address[0]) + self.send_response(200) + self.send_header("Content-type", "text/plain") + self.end_headers() + self.wfile.write(bytes(template_parsed, "utf-8")) + print('[%s] --> Success - %s bytes sent to client' % (self.client_address[0], len(template_parsed))) + else: + print('[%s] --> Error - could not find hostname "%s" in DB' % (self.client_address[0], hostname)) + else: + print('[%s] --> Rejected due to missing hostname' % self.client_address[0]) + + # Client asks for a file download - most likely a JunOS file + elif '/files/' in self.path: + # It seems that "http.server" escapes nastiness from the URL - ("/files/../../../root_file" => "/files/root_file") + requested_file = self.path.split('/files/')[1] + files_dir = 'fap/httpd/files/' + print('[%s] --> File request for "%s" in "%s"' % (self.client_address[0], requested_file, files_dir)) + if os.path.isfile(files_dir + requested_file): + print('[%s] --> File found' % self.client_address[0]) + try: + f = open(files_dir + requested_file) + self.send_response(200) + self.send_header('Content-type', 'application/x-gzip') # correct content type for tar.gz + self.end_headers() + print('[%s] --> File transfer started' % self.client_address[0]) + f = open(files_dir + requested_file, 'rb') + self.wfile.write(f.read()) + f.close() + print('[%s] --> File transfer completed' % self.client_address[0]) + return + except IOError: + self.send_error(404,'File Not Found: %s' % self.path) + print('[%s] --> ERROR 404 - File not found' % self.client_address[0]) + pass + except: + print('[%s] --> Generic error during file reading' % self.client_address[0]) + pass + else: + print('[%s] --> File request rejected due to nonexisting file' % self.client_address[0]) + else: + print('[%s] --> rejected due to bad URI' % self.client_address[0]) + # silence stderr from BaseHTTPRequestHandler + # source: http://stackoverflow.com/questions/3389305/how-to-silent-quiet-httpserver-and-basichttprequesthandlers-stderr-output + def log_message(self, format, *args): + return + + httpd_instance = HTTPServer((settings['http']['host'], settings['http']['port']), httpd) + print("\n[%s] Server Starts - %s:%s" % (time.asctime(), settings['http']['host'], settings['http']['port'])) + + try: + httpd_instance.serve_forever() + except KeyboardInterrupt: + pass + + httpd_instance.server_close() + print("\n\n[%s] HTTP Server stopped\n" % time.asctime()) + +if __name__ == "__main__": + main() diff --git a/fap/httpd/terminal.log b/fap/httpd/terminal.log new file mode 100644 index 0000000..bedb829 --- /dev/null +++ b/fap/httpd/terminal.log @@ -0,0 +1,14 @@ +j@lappie:~/git/tgmanage$ sudo python3 fap/httpd/server_http.py + +[Thu Feb 19 23:15:45 2015] Server Starts - 0.0.0.0:80 +[10.0.200.101] [Fri Feb 20 00:18:25 2015] Incoming HTTP GET URI://tg-edge/e-00-1 +[10.0.200.101] --> Hostname "e-00-1" accepted, fetching info from DB +[10.0.200.101] --> Template successfully populated +[10.0.200.101] --> Sending response to client +[10.0.200.101] --> Success - 1437 bytes sent to client +[10.0.200.101] [Fri Feb 20 00:18:26 2015] Incoming HTTP GET URI://files/jinstall-ex-2200-12.3R6.6-domestic-signed.tgz +[10.0.200.101] --> File request for "jinstall-ex-2200-12.3R6.6-domestic-signed.tgz" in "fap/httpd/files/" +[10.0.200.101] --> File found +[10.0.200.101] --> File transfer started +[10.0.200.101] --> File transfer completed + |