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
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.'}
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'}
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
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
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' }