summaryrefslogtreecommitdiff
path: root/roles/dyndns
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2019-01-12 05:54:28 +0100
committerChristian Pointner <equinox@spreadspace.org>2019-01-12 05:54:28 +0100
commit35d29d7335c59fe662a4485a2dd423ee82d64977 (patch)
tree8bdfb3f2d234bc59a8f1d879112e9646dc66195c /roles/dyndns
parentdyndns/client: minor cleanup (diff)
added dyndns/server role
Diffstat (limited to 'roles/dyndns')
-rw-r--r--roles/dyndns/client/tasks/main.yml3
-rw-r--r--roles/dyndns/server/tasks/main.yml21
-rwxr-xr-xroles/dyndns/server/templates/dyndns.py.j285
3 files changed, 108 insertions, 1 deletions
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 <equinox@spreadspace.org>
+#
+# 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 <http://www.gnu.org/licenses/>.
+#
+
+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 <allowed names>" 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)