tsig-keygen.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #!/usr/bin/env python
  2. """
  3. Pure Python TSIG key generator with multiple output formats.
  4. """
  5. import os, base64, argparse, jinja2
  6. algorithm_bits = dict(("hmac-sha{}".format(bits), bits // 8) for bits in (256, 384, 512))
  7. algorithm_choices = tuple(sorted(algorithm_bits))
  8. templates = dict(
  9. bind9 = '''
  10. key {{ args.name }} {
  11. algorithm {{ args.algorithm }};
  12. secret "{{ args.key }}";
  13. };
  14. {% if args.servers %}
  15. {%- for server in args.servers -%}
  16. server {{ server }} { keys { {{ args.name }}; }; };
  17. {% endfor -%}
  18. {% for zone in args.zones %}
  19. zone "{{ zone }}" {
  20. file "{{args.directory }}/{{ zone }}";
  21. type slave;
  22. masters { {%- for server in args.servers %} {{ server }}; {% endfor %} };
  23. };
  24. {% endfor %}
  25. {% endif %}
  26. ''',
  27. nsd = '''
  28. key:
  29. name: "{{ args.name }}"
  30. algorithm: {{ args.algorithm }}
  31. secret: "{{ args.key }}"
  32. {% if args.servers -%}
  33. pattern:
  34. name: "secondary.{{ args.name }}"
  35. zonefile: "{{ args.directory }}/%s"
  36. {%- for server in args.servers %}
  37. allow-notify: {{ server }} {{ args.name }}
  38. request-xfr: {{ server }} {{ args.name }}
  39. {%- endfor %}
  40. {%- for zone in args.zones %}
  41. zone:
  42. name: "{{ zone }}"
  43. include-pattern: "secondary.{{ args.name }}"
  44. {%- endfor %}
  45. {% endif %}
  46. ''')
  47. ap = argparse.ArgumentParser(description = __doc__)
  48. ap.add_argument("-a", "--algorithm", choices = algorithm_choices, default = algorithm_choices[0])
  49. ap.add_argument("-d", "--directory", default = "secondary", help = "where to store secondary zone files")
  50. ap.add_argument("-f", "--format", choices = tuple(templates), default = "nsd")
  51. ap.add_argument("-k", "--key", help = "TSIG shared secret (default: generate new secret)")
  52. ap.add_argument("-n", "--name", default = "tsig.example.org", help = "DNS name for TSIG shared secret")
  53. ap.add_argument("-o", "--output", default = "-", type = argparse.FileType("w"), help = "output file")
  54. ap.add_argument("-s", "--servers", nargs = "+", default = [], help = "address(es) of primary nameserver(s)")
  55. ap.add_argument("-z", "--zones", nargs = "+", default = [], help = "zone(s) to xfr from specified nameserver(s)")
  56. args = ap.parse_args()
  57. if args.key is None:
  58. args.key = base64.b64encode(os.urandom(algorithm_bits[args.algorithm])).decode("ascii")
  59. args.output.write(jinja2.Template(templates[args.format]).render(args = args))