ldap_netdb: Initial version of role
This commit is contained in:
parent
7b201b31da
commit
55d7d954b3
3 changed files with 192 additions and 0 deletions
|
@ -25,3 +25,5 @@
|
||||||
- base
|
- base
|
||||||
- ldap/server
|
- ldap/server
|
||||||
- kerberos/kdc
|
- kerberos/kdc
|
||||||
|
- role: ldap_netdb
|
||||||
|
when: ldap_master is defined
|
||||||
|
|
167
roles/ldap_netdb/files/netdb-update.py
Normal file
167
roles/ldap_netdb/files/netdb-update.py
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import ldap3
|
||||||
|
import syslog
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from base64 import b64decode
|
||||||
|
from email.utils import parsedate_to_datetime
|
||||||
|
from requests.packages.urllib3.exceptions import SubjectAltNameWarning
|
||||||
|
|
||||||
|
|
||||||
|
URL = "https://adm01.home.foo.sh/facts"
|
||||||
|
|
||||||
|
|
||||||
|
def get_url(URL):
|
||||||
|
return requests.get(
|
||||||
|
URL,
|
||||||
|
cert=(
|
||||||
|
"/etc/pki/tls/certs/ldap01.home.foo.sh.crt",
|
||||||
|
"/etc/pki/tls/private/ldap01.home.foo.sh.key",
|
||||||
|
),
|
||||||
|
verify="/etc/pki/tls/certs/ca.crt",
|
||||||
|
).json()
|
||||||
|
|
||||||
|
|
||||||
|
def get_hostlist():
|
||||||
|
for entry in get_url(URL):
|
||||||
|
mtime = parsedate_to_datetime(entry["mtime"])
|
||||||
|
yield (entry["name"], mtime)
|
||||||
|
|
||||||
|
|
||||||
|
def get_hostdata(hostname):
|
||||||
|
return get_url("{}/{}".format(URL, hostname))
|
||||||
|
|
||||||
|
|
||||||
|
def ldap_connect():
|
||||||
|
server = ldap3.Server("ldapi:///var/run/ldapi")
|
||||||
|
conn = ldap3.Connection(
|
||||||
|
server,
|
||||||
|
authentication=ldap3.SASL,
|
||||||
|
sasl_mechanism=ldap3.EXTERNAL,
|
||||||
|
sasl_credentials="",
|
||||||
|
client_strategy=ldap3.SYNC,
|
||||||
|
)
|
||||||
|
conn.bind()
|
||||||
|
conn.search(
|
||||||
|
search_base="",
|
||||||
|
search_filter="(objectClass=*)",
|
||||||
|
search_scope=ldap3.BASE,
|
||||||
|
attributes=["namingContexts"],
|
||||||
|
)
|
||||||
|
basedn = conn.response[0]["attributes"]["namingContexts"][0]
|
||||||
|
return (conn, basedn)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_certificate(data):
|
||||||
|
try:
|
||||||
|
return b64decode(data["ansible_local"]["ansible_certificate"])
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def parse_description(data):
|
||||||
|
osinfo = "{} {} ({})".format(
|
||||||
|
data["ansible_distribution"],
|
||||||
|
data["ansible_distribution_version"],
|
||||||
|
data["ansible_architecture"],
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
memory = data["ansible_memory_mb"]["real"]["total"]
|
||||||
|
except KeyError:
|
||||||
|
memory = data["ansible_memtotal_mb"]
|
||||||
|
if memory < 1024:
|
||||||
|
memory = "{} MB".format(memory)
|
||||||
|
else:
|
||||||
|
memory = "{} GB".format(round(memory / 1024, 1))
|
||||||
|
sysinfo = "{} CPU(s), {} GB memory".format(data["ansible_processor_count"], memory,)
|
||||||
|
if data["ansible_product_name"] == "KVM":
|
||||||
|
devinfo = "KVM - Guest"
|
||||||
|
else:
|
||||||
|
devinfo = "{} - {}".format(
|
||||||
|
data["ansible_system_vendor"], data["ansible_product_version"],
|
||||||
|
)
|
||||||
|
return "\n".join([devinfo, osinfo, sysinfo])
|
||||||
|
|
||||||
|
|
||||||
|
def parse_location(data):
|
||||||
|
return "Home"
|
||||||
|
|
||||||
|
|
||||||
|
def parse_sshkey(data):
|
||||||
|
try:
|
||||||
|
return "ssh-ed25519 {}".format(data["ansible_ssh_host_key_ed25519_public"])
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def parse_serial(data):
|
||||||
|
try:
|
||||||
|
serial = data["ansible_product_serial"]
|
||||||
|
if serial in ["NA", "System Serial Number"]:
|
||||||
|
return []
|
||||||
|
return serial
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def parse_objectclass(data):
|
||||||
|
objclass = ["device"]
|
||||||
|
if data["userCertificate;binary"] != []:
|
||||||
|
objclass.append("strongAuthenticationUser")
|
||||||
|
if data["sshPublicKey"] != []:
|
||||||
|
objclass.append("ldapPublicKey")
|
||||||
|
return objclass
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
requests.packages.urllib3.disable_warnings(SubjectAltNameWarning)
|
||||||
|
syslog.openlog(
|
||||||
|
sys.argv[0].split("/")[-1], logoption=syslog.LOG_PID, facility=syslog.LOG_DAEMON
|
||||||
|
)
|
||||||
|
(conn, basedn) = ldap_connect()
|
||||||
|
for (hostname, mtime) in get_hostlist():
|
||||||
|
dn = f"cn={hostname},ou=Hosts,{basedn}"
|
||||||
|
result = conn.search(
|
||||||
|
search_base=dn,
|
||||||
|
search_scope=ldap3.BASE,
|
||||||
|
search_filter=f"(&(objectClass=device)(cn={hostname}))",
|
||||||
|
attributes=[ldap3.ALL_ATTRIBUTES, "modifyTimeStamp"],
|
||||||
|
)
|
||||||
|
if result and conn.response[0]["attributes"]["modifyTimestamp"] > mtime:
|
||||||
|
continue
|
||||||
|
facts = get_hostdata(hostname)
|
||||||
|
|
||||||
|
# initialize data
|
||||||
|
if result:
|
||||||
|
ldap_data = dict(conn.response[0]["attributes"])
|
||||||
|
del ldap_data["modifyTimestamp"]
|
||||||
|
else:
|
||||||
|
ldap_data = {"cn": hostname}
|
||||||
|
|
||||||
|
ldap_data["userCertificate;binary"] = parse_certificate(facts)
|
||||||
|
ldap_data["description"] = parse_description(facts)
|
||||||
|
ldap_data["l"] = parse_location(facts)
|
||||||
|
ldap_data["sshPublicKey"] = parse_sshkey(facts)
|
||||||
|
ldap_data["serialNumber"] = parse_serial(facts)
|
||||||
|
ldap_data["objectClass"] = parse_objectclass(ldap_data)
|
||||||
|
if result:
|
||||||
|
for key in ldap_data:
|
||||||
|
ldap_data[key] = [(ldap3.MODIFY_REPLACE, ldap_data[key])]
|
||||||
|
syslog.syslog(syslog.LOG_INFO, f"Updating netdb data for host '{dn}'")
|
||||||
|
if not conn.modify(dn, ldap_data):
|
||||||
|
print(dn, conn.result)
|
||||||
|
else:
|
||||||
|
ldap_data = dict(filter(lambda x: x[1] != [], ldap_data.items()))
|
||||||
|
syslog.syslog(syslog.LOG_INFO, f"Adding netdb data for host '{dn}'")
|
||||||
|
if not conn.add(dn, attributes=ldap_data):
|
||||||
|
print(dn, conn.result)
|
||||||
|
syslog.closelog()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.exit(1)
|
23
roles/ldap_netdb/tasks/main.yml
Normal file
23
roles/ldap_netdb/tasks/main.yml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: install required python packages
|
||||||
|
package:
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: installed
|
||||||
|
with_items:
|
||||||
|
- python3-ldap3
|
||||||
|
- python3-requests
|
||||||
|
|
||||||
|
- name: install netdb-update script
|
||||||
|
copy:
|
||||||
|
src: netdb-update.py
|
||||||
|
dest: /usr/local/sbin/netdb-update
|
||||||
|
mode: 755
|
||||||
|
owner: root
|
||||||
|
group: "{{ ansible_wheel }}"
|
||||||
|
|
||||||
|
- name: install netdb-update cron job
|
||||||
|
cron:
|
||||||
|
name: update-netdb-data
|
||||||
|
minute: 10
|
||||||
|
job: /usr/local/sbin/netdb-upate
|
Loading…
Add table
Add a link
Reference in a new issue