From 35d29d7335c59fe662a4485a2dd423ee82d64977 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sat, 12 Jan 2019 05:54:28 +0100 Subject: added dyndns/server role --- roles/dyndns/client/tasks/main.yml | 3 +- roles/dyndns/server/tasks/main.yml | 21 ++++++++ roles/dyndns/server/templates/dyndns.py.j2 | 85 ++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 roles/dyndns/server/tasks/main.yml create mode 100755 roles/dyndns/server/templates/dyndns.py.j2 (limited to 'roles/dyndns') diff --git a/roles/dyndns/client/tasks/main.yml b/roles/dyndns/client/tasks/main.yml index ad470dad..027b6071 100644 --- a/roles/dyndns/client/tasks/main.yml +++ b/roles/dyndns/client/tasks/main.yml @@ -36,6 +36,7 @@ register: dyndns_ssh_keyscan - name: hack to make known_hosts work (1/2) + when: dyndns_ssh_keyscan is changed copy: content: "{{ dyndns_ssh_keyscan.stdout }}" dest: /var/lib/dyndns/.ssh/known_hosts @@ -44,7 +45,7 @@ # fix me -- name: install systemd uints +- name: install systemd units template: src: "dyndns.{{ item }}.j2" dest: "/etc/systemd/system/dyndns.{{ item }}" diff --git a/roles/dyndns/server/tasks/main.yml b/roles/dyndns/server/tasks/main.yml new file mode 100644 index 00000000..304a2473 --- /dev/null +++ b/roles/dyndns/server/tasks/main.yml @@ -0,0 +1,21 @@ +--- +- name: create user for dyndns + user: + name: dyndns + home: /var/lib/dyndns + system: yes + shell: /bin/sh + groups: bind + +- name: create .ssh directory + file: + path: /var/lib/dyndns/.ssh + mode: 0700 + owner: dyndns + group: dyndns + +- name: install zone update script + template: + src: dyndns.py.j2 + dest: /usr/local/bin/dyndns.py + mode: 0755 diff --git a/roles/dyndns/server/templates/dyndns.py.j2 b/roles/dyndns/server/templates/dyndns.py.j2 new file mode 100755 index 00000000..fbbd4f1a --- /dev/null +++ b/roles/dyndns/server/templates/dyndns.py.j2 @@ -0,0 +1,85 @@ +#!/usr/bin/python +# +# dyndns.py +# +# a simple ssh based dyndns updater for bind zone files +# +# Copyright (C) 2013 Christian Pointner +# +# This file is part of dyndns.py. +# +# dyndns.py is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# any later version. +# +# dyndns.py is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with dyndns.py. If not, see . +# + +from easyzone import easyzone +import subprocess + +import sys +import os +import re + +# +domain = '{{ dyndns.domain }}.' +zonefile = '{{ dyndns.zone_file }}' +rndc = '/usr/sbin/rndc' +### +# add this to the authorized key file of a system user +# the user needs to be a member of the bind group and must +# have write permissions to the zone file + +# no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding,no-user-rc,command="/usr/local/bin/dyndns.py " ssh-rsa ... +### + +if ('SSH_CLIENT' in os.environ) and ('SSH_ORIGINAL_COMMAND' in os.environ): + sshclient = os.environ['SSH_CLIENT'] + sshcmd = os.environ['SSH_ORIGINAL_COMMAND'] +else: + sys.stdout.write("Error: not an SSH connection\n") + sys.exit(1) + +name = sshcmd.split()[0] +if name not in set(sys.argv[1:]): + sys.stdout.write("Error: you are not allowed to update '%s'\n" % name) + sys.exit(1) + +ip = sshclient.split()[0] +if not re.match(r'^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$', ip): + sys.stdout.write("Error: not a valid IPv4 address\n") + sys.exit(1) + +name = name + '.' + domain +zone = easyzone.zone_from_file(domain, zonefile) +zone.add_name(name) +records = zone.names[name].records('A', create=True, ttl=60) +for item in records.get_items(): + if item == ip: + sys.stdout.write("Ok: nothing changed\n") + sys.exit(0) + + records.delete(item) + +records.add(ip) +zone.save(autoserial=True) + +cmd = [rndc, 'reload', domain] +p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) +output = '' +for line in p.stdout.readlines(): + output = output + line + +r = p.wait() +if r != 0: + sys.stdout.write("Error: rndc returned %d\n\n%s" % (r, output)) +else: + sys.stdout.write("Ok: " + output) -- cgit v1.2.3