MEschenbacher's Wireguard Saltstack Formula
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
4.6KB

  1. import yaml
  2. import os
  3. from tempfile import mkstemp
  4. __virtualname__ = 'wg'
  5. def __virtual__():
  6. # do checks for startup
  7. return __virtualname__
  8. def create(name):
  9. """
  10. create a wireguard interface. This will fail if it already exists.
  11. """
  12. ifaces = __salt__['network.interfaces']()
  13. if name not in ifaces.keys():
  14. __salt__['cmd.run']('ip link add %s type wireguard' % (name,))
  15. return {name: dict(new=name, old=None)}
  16. return 'Interface %s already exists' % (name,)
  17. def delete(name):
  18. """
  19. delete a interface (not neccessarily a wireguard interface). This will fail
  20. if it does not exist.
  21. """
  22. ifaces = __salt__['network.interfaces']()
  23. if name in ifaces.keys():
  24. __salt__['cmd.run']('ip link del %s' % (name,))
  25. return {name: dict(new=None, old=name)}
  26. return 'Interface %s does not exist' % (name,)
  27. def show(name=None, peer=None, hide_keys=True):
  28. if peer and not name:
  29. return 'If peer is given, name must also be given'
  30. if not name:
  31. return _wg_ifaces(hide_keys=hide_keys)
  32. elif peer:
  33. return _wg_ifaces(hide_keys=hide_keys).get(name).get('peers').get(peer)
  34. else:
  35. return _wg_ifaces(hide_keys=hide_keys).get(name)
  36. def showconf(name):
  37. return __salt__['cmd.run']('wg showconf %s' % (name,))
  38. def set(name, listen_port=None, fwmark=None, private_key=None, peer=None,
  39. preshared_key=None, endpoint=None, persistent_keepalive=None,
  40. allowed_ips=None, remove=False):
  41. s = 'wg set %s' % (name,)
  42. if remove:
  43. if not peer:
  44. return 'If remove is given, peer must also be given'
  45. return __salt__['cmd.run'](
  46. '%s peer %s remove' % (s, peer)
  47. )
  48. if listen_port:
  49. s = '%s listen-port %s' % (s, listen_port)
  50. if fwmark:
  51. s = '%s fwmark %s' % (s, fwmark)
  52. if private_key:
  53. fd, filename = mkstemp(text=True)
  54. with open(filename, 'w') as f:
  55. f.write(private_key)
  56. os.close(fd)
  57. s = '%s private-key %s' % (s, filename)
  58. if peer:
  59. s = '%s peer %s' % (s, peer)
  60. if preshared_key:
  61. if not peer:
  62. return 'If preshared_key is given, peer must also be given'
  63. fd2, filename2 = mkstemp(text=True)
  64. with open(filename2, 'w') as f:
  65. f.write(preshared_key)
  66. os.close(fd2)
  67. s = '%s preshared-key %s' % (s, filename2)
  68. if endpoint:
  69. if not peer:
  70. return 'If endpoint is given, peer must also be given'
  71. s = '%s endpoint %s' % (s, endpoint)
  72. if persistent_keepalive:
  73. if not peer:
  74. return 'If persistent_keepalive is given, peer must also be given'
  75. s = '%s persistent-keepalive %s' % (s, persistent_keepalive)
  76. if allowed_ips:
  77. if not peer:
  78. return 'If allowed_ips is given, peer must also be given'
  79. s = '%s allowed-ips %s' % (s, allowed_ips)
  80. r = __salt__['cmd.run'](s)
  81. if private_key:
  82. os.unlink(filename)
  83. if preshared_key:
  84. os.unlink(filename2)
  85. return r
  86. def remove_peer(name, peer):
  87. return __salt__['cmd.run'](
  88. 'wg set %s peer %s remove' % (name, peer)
  89. )
  90. # def add_peer(name, public_key, allowed_ips=None):
  91. # base = 'wg set %s peer %s' % (name, peer)
  92. #
  93. # return __salt__['cmd.run'](
  94. # )
  95. def genkey():
  96. return __salt__['cmd.run']('wg genkey')
  97. def genpsk():
  98. return __salt__['cmd.run']('wg genpsk')
  99. def setconf(name, path):
  100. return __salt__['cmd.run']('wg setconf %s %s' % (name, path))
  101. def addconf(name, path):
  102. return __salt__['cmd.run']('wg addconf %s %s' % (name, path))
  103. def _wg_ifaces(hide_keys=True):
  104. """
  105. Parse output from 'wg show'
  106. """
  107. # from https://github.com/saltstack/salt/blob/develop/salt/modules/linux_ip.py
  108. tmp = dict()
  109. tmpiface = dict()
  110. ifaces = dict()
  111. out = __salt__['cmd.run']('wg',
  112. env={'WG_HIDE_KEYS': 'always' if hide_keys else 'never'})
  113. for line in out.splitlines():
  114. if line.startswith('interface: '):
  115. k, v = _wg_splitline(line)
  116. ifaces[v] = dict(peers=dict())
  117. tmpiface = ifaces[v]
  118. tmp = tmpiface
  119. elif line.startswith('peer: '):
  120. k, v = _wg_splitline(line)
  121. tmpiface['peers'][v] = dict()
  122. tmp = tmpiface['peers'][v]
  123. elif line == '':
  124. continue
  125. k, v = _wg_splitline(line)
  126. if k == 'allowed ips':
  127. tmp[k] = [ s.strip() for s in v.split(',') ]
  128. else:
  129. tmp[k] = v
  130. return ifaces
  131. def _wg_splitline(line):
  132. parts = line.split(':', 1)
  133. return parts[0].strip(), parts[1].strip()