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.

137 lines
3.8KB

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