Skip to content
Snippets Groups Projects
Select Git revision
  • 9e22d0fb1c0878bdaf89d59233a82c9fa830ed41
  • master default protected
  • md-export
  • th/mail
  • 179-einladungen-zum-aushaengen-drucken
5 results

forms.py

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    zonedl.py 4.96 KiB
    #!/usr/bin/env python3
    
    import requests
    import bs4
    import argparse
    import getpass
    import subprocess
    import sys
    from pathlib import Path
    
    parser = argparse.ArgumentParser(
            description='Downloads a zone file from RWTH DNS-Admin-Portal.')
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('--list', action='store_true', default=False,
                       help='list available zones')
    group.add_argument('--zone', type=int, nargs='+', help='download zone by id')
    group.add_argument('--domain', nargs='+', help='download zone by name')
    parser.add_argument('--passwordstore', action='store', default=None,
                        help='password store entry used for login to the portal')
    parser.add_argument('dest', action='store', default='-', nargs='?',
                        help='destination for downloaded zone(s), - for stdout')
    args = parser.parse_args()
    
    NOC_PREFIX = 'https://noc-portal.rz.rwth-aachen.de'
    DNS_ADMIN = NOC_PREFIX + '/dnsadmin'
    ZONE_FILE = DNS_ADMIN + '/zones/{}-{}/pre_deploy_preview'
    SHIB_PREFIX = 'https://sso.rwth-aachen.de'
    SHIB_AUTH = SHIB_PREFIX + '/idp/profile/SAML2/Redirect/SSO'
    SHIB_REDIRECT = NOC_PREFIX + '/Shibboleth.sso/SAML2/POST'
    
    if args.passwordstore:
        prc = subprocess.run(['pass', 'show', args.passwordstore],
                             stdout=subprocess.PIPE, check=True)
        USERNAME = prc.stdout.splitlines()[1].strip()
        PASSWORD = prc.stdout.splitlines()[0].strip()
    else:
        USERNAME = input('Username: ')
        PASSWORD = getpass.getpass()
    
    
    def get_zones(session):
        r = session.get(DNS_ADMIN)
        if r.url.startswith(SHIB_AUTH):
            res, session, r = shib_auth(session, r)
            if not res:
                return {}
        b = bs4.BeautifulSoup(r.text, 'lxml')
        z = b.find(id='zones_table').find('tbody')
        d = {}
        for zone in z.find_all('tr'):
            a = zone.find('td').find('a')
            d[a.text] = int(a['href'].split('/')[-1].split('-', maxsplit=1)[0])
        return d
    
    
    def get_zone_file(session, zone):
        r = session.get(ZONE_FILE.format(str(zone[0]),
                        str(zone[1].replace('.', '-'))))
        if r.url.startswith(SHIB_AUTH):
            res, session, r = shib_auth(session, r)
            if not res:
                return ''
        b = bs4.BeautifulSoup(r.text, 'lxml')
        t = b.find(id='content-wrapper').find('div', class_='zone-content').text
        return t.replace('<br>', '').replace('\n\n', '\n')
    
    
    def shib_auth(session, resp, iterations=0):
        b = bs4.BeautifulSoup(resp.text, 'lxml')
        form = b.find('form')
        data = {}
        if form['name'] == 'loginformular':
            data = {'j_username': USERNAME,
                    'j_password': PASSWORD,
                    'donotcache': 'true',
                    '_shib_idp_revokeConsent': 'false',
                    '_eventId_proceed': '',
                    }
        elif form['name'] == 'form1':
            data = {'shib_idp_ls_exception.shib_idp_session_ss': '',
                    'shib_idp_ls_success.shib_idp_session_ss': 'false',
                    'shib_idp_ls_value.shib_idp_session_ss': '',
                    'shib_idp_ls_exception.shib_idp_persistent_ss': '',
                    'shib_idp_ls_success.shib_idp_persistent_ss': 'false',
                    'shib_idp_ls_value.shib_idp_persistent_ss': '',
                    'shib_idp_ls_supported': '',
                    '_eventId_proceed': '',
                    }
        r = session.post(SHIB_PREFIX+form['action'], data=data)
        b = bs4.BeautifulSoup(r.text, 'lxml')
        f = b.find('form')['action']
        if not f.startswith(SHIB_AUTH[len(SHIB_PREFIX):]):
            relaystate = b.find('input', attrs={'name': 'RelayState'})['value']
            samlresponse = b.find('input', attrs={'name': 'SAMLResponse'})['value']
            r = session.post(f, data={'RelayState': relaystate,
                                      'SAMLResponse': samlresponse})
            return True, session, r
        else:
            if iterations == 0:
                return shib_auth(session, r, 1)
            # authentication failed
            return False, session, r
    
    
    s = requests.session()
    d = get_zones(s)
    
    if args.dest == '-':
        fp = sys.stdout
    elif Path(args.dest).is_dir():
        fp = None
    else:
        fp = open(args.dest, 'w')
    
    if args.list:
        if fp is None:
            fp = open(str(Path(args.dest) / 'list'), 'w')
        for k in d:
            print('{}\t{}'.format(d[k], k), file=fp)
        sys.exit(0)
    
    wanted = []
    if args.domain:
        for k in d:
            if k in args.domain:
                wanted.append((d[k], k))
        for a in args.domain:
            if a not in d:
                print('Domain {} is not available, skipping'.format(a),
                      file=sys.stderr)
    else:
        zones = []
        for k in d:
            if d[k] in args.zone:
                wanted.append((d[k], k))
                zones.append(d[k])
        for a in args.zone:
            if a not in zones:
                print('Zone {} is not available, skipping'.format(a),
                      file=sys.stderr)
    
    if fp is None:
        for w in wanted:
            with open(str(Path(args.dest) / str(w[0])), 'w') as fp:
                fp.write(get_zone_file(s, w))
    else:
        for w in wanted:
            fp.write(get_zone_file(s, w))