Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for managing wildcard records #9

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ chmod +x ionos_dyndns.py

### General
```
usage: ionos_dyndns.py [-h] [-4] [-6] [-i] [-H] --api-prefix --api-secret
usage: ionos_dyndns.py [-h] [-4] [-6] [-i] [-H] [-W] --api-prefix --api-secret

Create and update DNS records for this host using IONOS' API to use as a sort of DynDNS (for example via a cronjob).

Expand All @@ -50,6 +50,7 @@ optional arguments:
-6, --AAAA Create/Update AAAA record
-i , --interface Interface name for determining the public IPv6 address (Default: eth0)
-H , --fqdn Host's FQDN (Default: hostname -f)
-W --wildcard Create/Update Wildcard A/AAAA record (Default: False)
--api-prefix API key publicprefix
--api-secret API key secret
```
Expand Down
39 changes: 27 additions & 12 deletions ionos_dyndns.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ def parse_cmdline_args():
metavar="",
help="API key secret"
)
argparser.add_argument(
"-W", "--wildcard",
default=False,
action="store_const",
const=True,
help="Create/Update Wildcard records with current action (A or AAAA) (Dgiefault: False)"
)

args = argparser.parse_args()

Expand Down Expand Up @@ -89,24 +96,30 @@ def main():

domain = get_domain_from_fqdn(fqdn)
zone = get_zone(domain)
all_records = get_all_records_for_fqdn(zone["id"], fqdn)
all_records = get_all_records_for_fqdn(zone["id"], fqdn, args.wildcard)
records_to_create = []
records_to_update = []

# Code duplication. Could use some refactoring but I don't have time for this atm
if args.A:
ipv4_address = get_ipv4_address()
logging.info("Public IPv4: " + ipv4_address)
if filter_records_by_type(all_records, "A"):
if filter_records_by_type(all_records, "A")[0]["content"] == ipv4_address:
logging.info("A record is up-to-date")
else:
logging.info("A record is outdated")
records_to_update.append(
new_record(fqdn, "A", ipv4_address, 60))
else:
records_filtered = filter_records_by_type(all_records, "A")
if not records_filtered:
logging.info("No A record found")
records_to_create.append(new_record(fqdn, "A", ipv4_address, 60))
if args.wildcard:
logging.info("No Wildcard A record found")
records_to_create.append(new_record("*." + fqdn, "A", ipv4_address, 60))
else:
for record in records_filtered:
log_prefix = "Wildcard " if "*" in record["name"] else ""
if record["content"] == ipv4_address:
logging.info(f"{log_prefix}A record is up-to-date")
else:
record_name = "*." + fqdn if "*" in record["name"] else fqdn
logging.info(f"{log_prefix}A record is outdated")
records_to_update.append(new_record(record_name, "A", ipv4_address, 60))

# Good god this is ugly. I hate myself for writing this. This really needs refactoring...
if args.AAAA:
Expand Down Expand Up @@ -146,7 +159,8 @@ def get_ipv4_address():


def get_ipv6_address(interface_name):
ip_output = subprocess.getoutput(f"ip -6 -o address show dev {interface_name} scope global | grep --invert temporary | grep --invert mngtmpaddr")
ip_output = subprocess.getoutput(
f"ip -6 -o address show dev {interface_name} scope global | grep --invert temporary | grep --invert mngtmpaddr")
if ip_output != "":
ip_output_regex = r"(?:inet6)(?:\s+)(.+)(?:\/\d{1,3})"
return re.search(ip_output_regex, ip_output, re.IGNORECASE).group(1)
Expand All @@ -160,10 +174,11 @@ def get_zone(domain):
return list(filter(lambda zone: zone['name'] == domain, response))[0]


def get_all_records_for_fqdn(zone_id, host):
def get_all_records_for_fqdn(zone_id, host, wildcard=False):
url = f"{api_url}/{zone_id}"
records = json.loads(requests.request("GET", url, headers=api_headers).text)['records']
return list(filter(lambda record: record['name'] == host, records))
return list(
filter(lambda record: record['name'] == host or (wildcard is True and record['name'] == '*.' + host), records))


def filter_records_by_type(records, type):
Expand Down