Exemplo n.º 1
0
 def remove_all(cls):
     """Remove all history from DB."""
     try:
         db.session.query(History).delete()
         db.session.commit()
         LOGGING.info("Removed all history")
         return True
     except Exception:
         db.session.rollback()
         LOGGING.error("Cannot remove history")
         LOGGING.debug(traceback.format_exc())
         return False
Exemplo n.º 2
0
    def add(cls,
            domain_name,
            domain_type,
            soa_edit_api,
            domain_ns=None,
            domain_master_ips=None):
        """Add a domain to power dns."""
        if not domain_ns:
            domain_ns = [
                'dns001.den01.pop', 'dns002.den01.pop', 'dns001.iad02.pop',
                'dns002.iad02.pop', 'dns001.sin01.pop', 'dns002.sin01.pop',
                'dns001.ams01.pop', 'dns002.ams01.pop'
            ]
        if not domain_master_ips:
            domain_master_ips = []
        headers = {}
        headers['X-API-Key'] = PDNS_API_KEY

        domain_name = domain_name + '.'
        domain_ns = [ns + '.' for ns in domain_ns]

        post_data = {
            "name": domain_name,
            "kind": domain_type,
            "masters": domain_master_ips,
            "nameservers": domain_ns,
        }

        if soa_edit_api != 'OFF':
            post_data["soa_edit_api"] = soa_edit_api

        try:
            jdata = utils.fetch_json(urlparse.urljoin(
                PDNS_STATS_URL, API_EXTENDED_URL + '/servers/localhost/zones'),
                                     headers=headers,
                                     method='POST',
                                     data=post_data)
            if 'error' in jdata.keys():
                LOGGING.error(jdata['error'])
                return {'status': 'error', 'msg': jdata['error']}
            else:
                LOGGING.info('Added domain %s successfully', domain_name)
                return {'status': 'ok', 'msg': 'Added domain successfully'}
        except Exception as err:
            LOGGING.error('Cannot add domain %s', domain_name)
            traceback.format_exc()
            LOGGING.debug(str(err))
            return {'status': 'error', 'msg': 'Cannot add this domain.'}
Exemplo n.º 3
0
 def delete(cls, domain_name):
     """Delete a single domain name from powerdns."""
     headers = {}
     headers['X-API-Key'] = PDNS_API_KEY
     try:
         url = urlparse.urljoin(
             PDNS_STATS_URL,
             API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain_name)
         utils.fetch_json(url, headers=headers, method='DELETE')
         LOGGING.info('Delete domain %s successfully', domain_name)
         return {'status': 'ok', 'msg': 'Delete domain successfully'}
     except Exception as e:
         tbck = traceback.format_exc()
         LOGGING.error('Cannot delete domain %s', domain_name)
         LOGGING.debug(str(e))
         LOGGING.debug(str(tbck))
         return {'status': 'error', 'msg': 'Cannot delete domain'}
Exemplo n.º 4
0
    def check_passwd_ldap(self, validate_thispass=None):
        """Check to see if this user will authenticate with LDAP."""
        if not LDAP_TYPE:
            LOGGING.error('LDAP authentication is disabled')
            return False

        searchFilter = "(&(objectcategory=person)(samaccountname=%s))" % self.username
        if LDAP_TYPE == 'ldap':
            searchFilter = "(&(%s=%s)%s)" % (LDAP_USERNAMEFIELD, self.username,
                                             LDAP_FILTER)
            LOGGING.info('Ldap searchFilter "%s"', searchFilter)

        result = self.ldap_search(searchFilter, LDAP_SEARCH_BASE)
        if not result:
            LOGGING.warning('User "%s" does not exist', self.username)
            return False

        ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
        ldp = ldap.initialize(LDAP_URI)
        ldp.set_option(ldap.OPT_REFERRALS, 0)
        ldp.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
        ldp.set_option(ldap.OPT_X_TLS, ldap.OPT_X_TLS_DEMAND)
        ldp.set_option(ldap.OPT_X_TLS_DEMAND, True)
        ldp.set_option(ldap.OPT_DEBUG_LEVEL, 255)
        ldp.protocol_version = ldap.VERSION3
        if not validate_thispass:
            validate_thispass = self.password

        try:
            ldap_username = result[0][0][0]
            ldp.simple_bind_s(ldap_username, validate_thispass)
            LOGGING.info('User "%s" logged in successfully', self.username)
        except Exception:
            LOGGING.error('User "%s" input a wrong password', self.username)
            return False

        # create user if not exist in the db
        if not User.query.filter(User.username == self.username).first():
            try:
                # try to get user's firstname & lastname from LDAP
                # this might be changed in the future
                self.firstname = result[0][0][1]['givenName'][0]
                self.lastname = result[0][0][1]['sn'][0]
                self.email = result[0][0][1]['mail'][0]
            except Exception:
                self.firstname = self.username
                self.lastname = ''

            # first register user will be in Administrator role
            self.role_id = Role.query.filter_by(name='User').first().id
            if User.query.count() == 0:
                self.role_id = Role.query.filter_by(
                    name='Administrator').first().id

            self.create_user()
            LOGGING.info('Created user "%s" in the DB', self.username)

        return True
Exemplo n.º 5
0
    def is_validate(self, method):
        """Validate user credential."""
        if method == 'LOCAL':
            user_info = User.query.filter(
                User.username == self.username).first()

            if user_info:
                if user_info.password and self.check_passwd_local(
                        user_info.password):
                    LOGGING.info('User "%s" logged in successfully',
                                 self.username)
                    return True
                LOGGING.error('User "%s" input a wrong password',
                              self.username)
                return False

            LOGGING.warning('User "%s" does not exist', self.username)
            return False

        if method == 'LDAP':
            return self.check_passwd_ldap()

        LOGGING.error('Unsupported authentication method')
        return False
Exemplo n.º 6
0
    def apply(self, domain, post_records):
        """Apply record changes to domain."""
        # pylint: disable=R0912,R0915,R0914
        LOGGING.info('apply() domain is %s', (domain))
        records = []
        for r in post_records:
            r_name = domain if r['record_name'] in [
                '@', ''
            ] else r['record_name'] + '.' + domain
            r_type = r['record_type']
            if PRETTY_IPV6_PTR:  # only if activated
                if NEW_SCHEMA:  # only if new schema
                    if r_type == 'PTR':  # only ptr
                        if ':' in r['record_name']:  # dirty ipv6 check
                            r_name = r['record_name']

            record = {
                "name": r_name,
                "type": r_type,
                "content": r['record_data'],
                "disabled":
                True if r['record_status'] == 'Disabled' else False,
                "ttl": int(r['record_ttl']) if r['record_ttl'] else 3600,
            }
            records.append(record)

        deleted_records, new_records = self.compare(domain, records)

        self.records_delete = []
        for r in deleted_records:
            r_name = r['name'].rstrip('.') + '.' if NEW_SCHEMA else r['name']
            r_type = r['type']
            if PRETTY_IPV6_PTR:  # only if activated
                if NEW_SCHEMA:  # only if new schema
                    if r_type == 'PTR':  # only ptr
                        if ':' in r['name']:  # dirty ipv6 check
                            r_name = dns.reversename.from_address(
                                r['name']).to_text()

            record = {
                "name": r_name,
                "type": r_type,
                "changetype": "DELETE",
                "records": [],
            }
            self.records_delete.append(record)

        # postdata_for_delete = {"rrsets": self.records_delete}

        records = []
        for r in new_records:
            if NEW_SCHEMA:
                r_name = r['name'].rstrip('.') + '.'
                r_type = r['type']
                if PRETTY_IPV6_PTR:  # only if activated
                    if r_type == 'PTR':  # only ptr
                        if ':' in r['name']:  # dirty ipv6 check
                            r_name = r['name']

                record = {
                    "name":
                    r_name,
                    "type":
                    r_type,
                    "changetype":
                    "REPLACE",
                    "ttl":
                    r['ttl'],
                    "records": [{
                        "content": r['content'],
                        "disabled": r['disabled'],
                    }]
                }
            else:
                # priority field for pdns 3.4.1.
                # https://doc.powerdns.com/md/authoritative/upgrading/
                record = {
                    "name":
                    r['name'],
                    "type":
                    r['type'],
                    "changetype":
                    "REPLACE",
                    "records": [{
                        "content": r['content'],
                        "disabled": r['disabled'],
                        "name": r['name'],
                        "ttl": r['ttl'],
                        "type": r['type'],
                        "priority": 10,
                    }]
                }

            records.append(record)

        # Adjustment to add multiple records which described in
        # https://github.com/ngoduykhanh/PowerDNS-Admin/issues/5#issuecomment-181637576
        self.fnl_recs = []
        records = sorted(records,
                         key=lambda item:
                         (item["name"], item["type"], item["changetype"]))
        for key, group in itertools.groupby(
                records, lambda item:
            (item["name"], item["type"], item["changetype"])):
            if NEW_SCHEMA:
                r_name = key[0]
                r_type = key[1]
                r_changetype = key[2]

                if PRETTY_IPV6_PTR:  # only if activated
                    if r_type == 'PTR':  # only ptr
                        if ':' in r_name:  # dirty ipv6 check
                            r_name = dns.reversename.from_address(
                                r_name).to_text()

                new_record = {
                    "name": r_name,
                    "type": r_type,
                    "changetype": r_changetype,
                    "ttl": None,
                    "records": [],
                }
                for item in group:
                    temp_content = item['records'][0]['content']
                    temp_disabled = item['records'][0]['disabled']
                    if key[1] in ['MX', 'CNAME', 'SRV', 'NS']:
                        if temp_content.strip()[-1:] != '.':
                            temp_content += '.'

                    if new_record['ttl'] is None:
                        new_record['ttl'] = item['ttl']
                    new_record['records'].append({
                        "content": temp_content,
                        "disabled": temp_disabled
                    })
                self.fnl_recs.append(new_record)

            else:

                self.fnl_recs.append({
                    "name":
                    key[0],
                    "type":
                    key[1],
                    "changetype":
                    key[2],
                    "records": [{
                        "content": item['records'][0]['content'],
                        "disabled": item['records'][0]['disabled'],
                        "name": key[0],
                        "ttl": item['records'][0]['ttl'],
                        "type": key[1],
                        "priority": 10,
                    } for item in group]
                })
        self.final_records_limit()
        postdata_for_changes = {"rrsets": self.net_final}
        LOGGING.info('apply() postdata_for_changes is %s',
                     (json.dumps(postdata_for_changes)))

        try:
            headers = {}
            headers['X-API-Key'] = PDNS_API_KEY
            url = urlparse.urljoin(
                PDNS_STATS_URL,
                API_EXTENDED_URL + '/servers/localhost/zones/%s' % domain)
            # utils.fetch_json(url, headers=headers, method='PATCH', data=postdata_for_delete)
            jdata2 = utils.fetch_json(url,
                                      headers=headers,
                                      method='PATCH',
                                      data=postdata_for_changes)

            if 'error' in jdata2.keys():
                LOGGING.error('Cannot apply record changes.')
                LOGGING.debug(jdata2['error'])
                return {'status': 'error', 'msg': jdata2['error']}
            else:
                # should this get postdata_for_changes ??? instead of the deprecated new_records, deleted_records
                # postdata_for_changes is final_records_limit
                if not re.search('in-addr.arpa', domain):
                    self.auto_ptr(domain)

                LOGGING.debug("update dyndns data: %s", postdata_for_changes)
                LOGGING.debug("update dyndns url: %s", url)

                LOGGING.info('Record was applied successfully.')
                self.history_log_apply(domain)
                return {
                    'status': 'ok',
                    'msg': 'Record was applied successfully'
                }

        except Exception as error:
            LOGGING.error(
                "Cannot apply record changes to domain %s. DETAIL: %s",
                str(error), domain)
            return {
                'status': 'error',
                'msg':
                'There was something wrong, please contact administrator'
            }