From b414a94e17c0e17429a1a592120c772f568ad1ce Mon Sep 17 00:00:00 2001 From: Markus Pesch Date: Mon, 21 Feb 2022 22:35:01 +0100 Subject: [PATCH] Initial Commit --- .ansible-lint | 3 + .drone.yml | 94 ++++++++++++++++++++++++++ .editorconfig | 12 ++++ .markdownlint.yaml | 144 ++++++++++++++++++++++++++++++++++++++++ LICENSE | 20 ++++++ README.md | 26 ++++++++ defaults/main.yml | 35 ++++++++++ handlers/main.yml | 7 ++ meta/main.yml | 22 ++++++ renovate.json | 17 +++++ tasks/main.yml | 62 +++++++++++++++++ templates/dhcpd.conf.j2 | 109 ++++++++++++++++++++++++++++++ vars/Archlinux.yml | 13 ++++ vars/Debian.yml | 13 ++++ vars/RedHat.yml | 13 ++++ 15 files changed, 590 insertions(+) create mode 100644 .ansible-lint create mode 100644 .drone.yml create mode 100644 .editorconfig create mode 100644 .markdownlint.yaml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 meta/main.yml create mode 100644 renovate.json create mode 100644 tasks/main.yml create mode 100644 templates/dhcpd.conf.j2 create mode 100644 vars/Archlinux.yml create mode 100644 vars/Debian.yml create mode 100644 vars/RedHat.yml diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 0000000..dff231b --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,3 @@ +--- + +skip_list: [] \ No newline at end of file diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..2f437bb --- /dev/null +++ b/.drone.yml @@ -0,0 +1,94 @@ +--- +kind: pipeline +type: kubernetes +name: linter + +platform: + os: linux + +steps: +- name: markdown lint + commands: + - markdownlint *.md + image: docker.io/volkerraschek/markdownlint:0.31.1 + resources: + limits: + cpu: 50 + memory: 50M + +- name: email-notification + environment: + PLUGIN_HOST: + from_secret: smtp_host + PLUGIN_USERNAME: + from_secret: smtp_username + PLUGIN_PASSWORD: + from_secret: smtp_password + PLUGIN_FROM: + from_secret: smtp_mail_address + image: docker.io/drillster/drone-email:latest + resources: + limits: + cpu: 50 + memory: 25M + when: + status: + - changed + - failure + +trigger: + event: + exclude: + - tag + +--- +kind: pipeline +type: kubernetes +name: sync + +platform: + os: linux + arch: amd64 + +steps: +- name: github + image: docker.io/appleboy/drone-git-push:latest + resources: + limits: + cpu: 50 + memory: 25M + settings: + branch: master + remote: ssh://git@github.com/volker-raschek/dhcpd-role.git + force: true + ssh_key: + from_secret: ssh_key + +- name: email-notification + environment: + PLUGIN_HOST: + from_secret: smtp_host + PLUGIN_USERNAME: + from_secret: smtp_username + PLUGIN_PASSWORD: + from_secret: smtp_password + PLUGIN_FROM: + from_secret: smtp_mail_address + image: docker.io/drillster/drone-email:latest + resources: + limits: + cpu: 50 + memory: 25M + when: + status: + - changed + - failure + +trigger: + branch: + - master + event: + - cron + - push + repo: + - volker.raschek/dhcpd-role diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1166a4a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = false \ No newline at end of file diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..3406b43 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,144 @@ +# markdownlint YAML configuration +# https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml + +# Default state for all rules +default: true + +# Path to configuration file to extend +extends: null + +# MD003/heading-style/header-style - Heading style +MD003: + # Heading style + style: "atx" + +# MD004/ul-style - Unordered list style +MD004: + style: "dash" + +# MD007/ul-indent - Unordered list indentation +MD007: + # Spaces for indent + indent: 2 + # Whether to indent the first level of the list + start_indented: false + +# MD009/no-trailing-spaces - Trailing spaces +MD009: + # Spaces for line break + br_spaces: 2 + # Allow spaces for empty lines in list items + list_item_empty_lines: false + # Include unnecessary breaks + strict: false + +# MD010/no-hard-tabs - Hard tabs +MD010: + # Include code blocks + code_blocks: true + +# MD012/no-multiple-blanks - Multiple consecutive blank lines +MD012: + # Consecutive blank lines + maximum: 1 + +# MD013/line-length - Line length +MD013: + # Number of characters + line_length: 80 + # Number of characters for headings + heading_line_length: 80 + # Number of characters for code blocks + code_block_line_length: 80 + # Include code blocks + code_blocks: false + # Include tables + tables: false + # Include headings + headings: true + # Include headings + headers: true + # Strict length checking + strict: false + # Stern length checking + stern: false + +# MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines +MD022: + # Blank lines above heading + lines_above: 1 + # Blank lines below heading + lines_below: 1 + +# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content +MD024: + # Only check sibling headings + allow_different_nesting: true + +# MD025/single-title/single-h1 - Multiple top-level headings in the same document +MD025: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD026/no-trailing-punctuation - Trailing punctuation in heading +MD026: + # Punctuation characters + punctuation: ".,;:!。,;:!" + +# MD029/ol-prefix - Ordered list item prefix +MD029: + # List style + style: "one_or_ordered" + +# MD030/list-marker-space - Spaces after list markers +MD030: + # Spaces for single-line unordered list items + ul_single: 1 + # Spaces for single-line ordered list items + ol_single: 1 + # Spaces for multi-line unordered list items + ul_multi: 1 + # Spaces for multi-line ordered list items + ol_multi: 1 + +# MD033/no-inline-html - Inline HTML +MD033: + # Allowed elements + allowed_elements: [] + +# MD035/hr-style - Horizontal rule style +MD035: + # Horizontal rule style + style: "---" + +# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading +MD036: + # Punctuation characters + punctuation: ".,;:!?。,;:!?" + +# MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading +MD041: + # Heading level + level: 1 + # RegExp for matching title in front matter + front_matter_title: "^\\s*title\\s*[:=]" + +# MD044/proper-names - Proper names should have the correct capitalization +MD044: + # List of proper names + names: + - gitea + # Include code blocks + code_blocks: false + +# MD046/code-block-style - Code block style +MD046: + # Block style + style: "fenced" + +# MD048/code-fence-style - Code fence style +MD048: + # Code fence syle + style: "backtick" \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..51ff935 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2022 Markus Pesch + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a03aaa0 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# dhcpd + +[![Build Status](https://drone.cryptic.systems/api/badges/volker.raschek/dhcpd-role/status.svg)](https://drone.cryptic.systems/volker.raschek/dhcpd-role) +[![Ansible Role](https://img.shields.io/ansible/role/d/58170)](https://galaxy.ansible.com/volker_raschek/dhcpd_role) + +With following role can be dhcpd installed and configured. + +## Supported distributions + +- Arch Linux +- Rocky Linux 8 +- Ubuntu 20.04 + +## Features + +- Installing dhcpd +- Configuring dhcpd + - TSIG-Keys + - Simple Zones + - Multiple subnets listen on different interfaces + - DYNDNS + +## Configuring + +In the default directory are examples how to configure `dhcpd`. Copy the +defaults into your `host_vars` or `group_vars` and adapt the examples. \ No newline at end of file diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..274afd1 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,35 @@ +--- + +dhcpd_keys: [] +# - name: dyndns +# algorithm: hmac-sha512 +# secret: secret-of-tsig-key + +dhcpd_static_hosts: [] +# - name: "my-host" +# hardware_ethernet: "ac:e4:b5:a5:4f:e4" +# ddns_hostname: "my-host" +# fixed_address: "111.222.111.222" + +dhcpd_subnets: [] +# - interface: "enp7s0" +# network_start: "192.168.181.0" +# network_netmask: "255.255.255.0" +# network_range: "192.168.181.20 192.168.181.200" +# default_lease_time: "43200" +# max_lease_time: "2168640000" +# min_lease_time: "21600" +# ddns_domainname: "example.com" +# option_broadcast_address: "192.168.181.255" +# option_domain_name: "example.com" +# option_domain_name_servers: "192.168.181.1" +# option_routers: "192.168.181.1" +# option_subnet_mask: "255.255.255.0" + +dhcpd_zones: [] +# - name: example.com +# primary: 192.168.181.1 +# key: dyndns +# - name: 181.168.192.in-addr.arpa +# primary: 192.168.181.1 +# key: dyndns \ No newline at end of file diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..c21c700 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,7 @@ +--- + +- name: restart dhcpd + systemd: + name: "{{ dhcpd_service_name }}" + state: restarted + daemon_reload: true \ No newline at end of file diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..f4e6073 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,22 @@ +galaxy_info: + author: Markus Pesch + description: Role to install and configure dhcpd on different distributions + company: Cryptic Systems + license: MIT + min_ansible_version: 2.1 + platforms: + - name: Archlinux + versions: + - all + - name: Ubuntu + versions: + - 20.04 + - name: RockyLinux + versions: + - 8.5 + + galaxy_tags: + - dhcpd + - dyndns + +dependencies: [] diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..0eb214c --- /dev/null +++ b/renovate.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "assignees": [ "volker.raschek" ], + "automergeStrategy": "merge-commit", + "automergeType": "pr", + "labels": [ "renovate" ], + "packageRules": [ + { + "addLabels": [ "renovate/droneci", "renovate/automerge" ], + "automerge": true, + "matchManagers": "droneci", + "matchUpdateTypes": [ "minor", "patch"] + } + ], + "rebaseLabel": "renovate/rebase", + "rebaseWhen": "behind-base-branch" +} diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..52ea76f --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,62 @@ +--- + +- name: check if at least one subnet is defined + assert: + that: + - dhcpd_subnets | length > 0 + fail_msg: "No subnet defined" + +- name: include special distribution-dependent variables + include_vars: "{{ ansible_os_family }}.yml" + +- name: install dhcpd with dependencies + package: + name: "{{ item }}" + state: present + with_items: + - "{{ dhcpd_package_names }}" + +- name: create dhcpd config + template: + src: "dhcpd.conf.j2" + dest: "{{ dhcpd_main_config }}" + owner: "{{ dhcpd_unix_user }}" + group: "{{ dhcpd_unix_group }}" + mode: 0644 + +- name: cleanup cache files + block: + - name: check if cache dir exists + stat: + path: "{{ dhcpd_cache_directory }}" + register: cache_stats + - name: remove cache dir + file: + path: "{{ dhcpd_cache_directory }}" + state: absent + when: cache_stats.stat.exists + - name: create cache dir + file: + path: "{{ dhcpd_cache_directory }}" + owner: "{{ dhcpd_unix_user }}" + group: "{{ dhcpd_unix_group }}" + mode: 0755 + state: directory + - name: create cache files + file: + path: "{{ dhcpd_cache_directory }}/{{ item }}" + owner: "{{ dhcpd_unix_user }}" + group: "{{ dhcpd_unix_group }}" + mode: 0644 + state: touch + with_items: + - dhcpd.leases + notify: restart dhcpd + +- name: start and enable dhcpd + systemd: + name: "{{ item }}" + state: started + enabled: yes + with_items: + - "{{ dhcpd_service_name }}" \ No newline at end of file diff --git a/templates/dhcpd.conf.j2 b/templates/dhcpd.conf.j2 new file mode 100644 index 0000000..2f22d47 --- /dev/null +++ b/templates/dhcpd.conf.j2 @@ -0,0 +1,109 @@ +# +# {{ ansible_managed }} +# + +# If this DHCP server is the official DHCP server for the local +# network, the authoritative directive should be uncommented. +authoritative; + +# The style parameter must be one of ad-hoc, interim or none. The +# ddns-update-style statement is only meaningful in the outer scope - it +# is evaluated once after reading the dhcpd.conf file, rather than each +# time a client is assigned an IP address, so there is no way to use +# different DNS update styles for different clients. The default is +# nonrent DNS update styles for different clients. The default is none. +ddns-update-style interim; + +# The first point to understand about this style of DNS update is that +# unlike the ad-hoc style, the DHCP server does not necessarily always +# update both the A and the PTR records. The FQDN option includes a flag +# which, when sent by the client, indicates that the client wishes to +# update its own A record. In that case, the server can be configured +# either to honor the client’s intentions or ignore them. This is +# done with the statement allow client-updates; or the statement ignore +# client-updates;. By default, client updates are allowed. +ignore client-updates; + +{% for key in dhcpd_keys %} +key "{{ key.name }}" { + algorithm {{ key.algorithm }}; + secret "{{ key.secret }}"; +} +{% endfor %} + +{% for zone in dhcpd_zones %} +zone {{ zone.name }} { + primary {{ zone.primary }}; + key "{{ zone.key }}"; +} +{% endfor %} + +{% for subnet in dhcpd_subnets %} +subnet {{ subnet.network_start }} netmask {{ subnet.network_netmask }} { + interface {{ subnet.interface }}; + + range {{ subnet.network_range }}; + + # Time should be the length in seconds that will be assigned to a + # lease if the client requesting the lease does not ask for a specific + # expiration time. This is used for both DHCPv4 and DHCPv6 leases (it + # is also known as the "valid lifetime" in DHCPv6). + default-lease-time {{ subnet.default_lease_time }}; + + # Time should be the maximum length in seconds that will be assigned + # to a lease. If not defined, the default maximum lease time is 86400. + # The only exception to this is that Dynamic BOOTP lease lengths, + # which are not specified by the client, are not limited by this + # maximum. + max-lease-time {{ subnet.max_lease_time }}; + + # Time should be the minimum length in seconds that will be assigned + # to a lease. The default is the minimum of 300 seconds or + # max-lease-time. + min-lease-time {{ subnet.min_lease_time }}; + + # The name parameter should be the domain name that will be appended + # to the client's hostname to form a fully-qualified domain-name + # (FQDN). + ddns-domainname "{{ subnet.ddns_domainname }}"; + + # The update-static-leases flag, if enabled, causes the DHCP server to + # do DNS updates for clients even if those clients are being assigned + # their IP address using a fixed-address statement - that is, the + # client is being given a static assignment. This can only work with + # the interim DNS update scheme. It is not recommended because the + # DHCP server has no way to tell that the update has been done, and + # therefore will not delete the record when it is not in use. Also, + # the server must attempt the update each time the client renews its + # lease, which could have a significant performance impact in + # environments that place heavy demands on the DHCP server. + update-static-leases on; + + option broadcast-address {{ subnet.option_broadcast_address }}; + # option domain-name "{{ subnet.option_domain_name }}"; + option domain-name-servers {{ subnet.option_domain_name_servers }}; + option routers {{ subnet.option_routers }}; + option subnet-mask {{ subnet.option_subnet_mask }}; + + # PXE-Boot-Settings + # allow booting; + # allow bootp; + # next-server 192.168.179.15; + # filename "pxelinux.0"; +} +{% endfor %} + +{% if dhcpd_static_hosts is defined and dhcpd_static_hosts | length > 0 %} +{% for host in dhcpd_static_hosts %} +host {{ host.name }} { +{% if host.ddns_hostname is defined %} + ddns-hostname {{ host.ddns_hostname }}; +{% endif %} +{% if host.fixed_address is defined %} + fixed-address {{ host.fixed_address }}; +{% endif %} + hardware ethernet {{ host.hardware_ethernet }}; +} + +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/vars/Archlinux.yml b/vars/Archlinux.yml new file mode 100644 index 0000000..f4c10fd --- /dev/null +++ b/vars/Archlinux.yml @@ -0,0 +1,13 @@ +--- + +dhcpd_main_config: /etc/dhcpd.conf + +dhcpd_cache_directory: /var/lib/dhcp + +dhcpd_package_names: +- dhcp + +dhcpd_service_name: dhcpd4 + +dhcpd_unix_user: dhcp +dhcpd_unix_group: dhcp diff --git a/vars/Debian.yml b/vars/Debian.yml new file mode 100644 index 0000000..8d3f79d --- /dev/null +++ b/vars/Debian.yml @@ -0,0 +1,13 @@ +--- + +dhcpd_main_config: /etc/dhcp/dhcpd.conf + +dhcpd_cache_directory: /var/lib/dhcp + +dhcpd_package_names: +- isc-dhcp-server + +dhcpd_service_name: isc-dhcp-server + +dhcpd_unix_user: dhcpd +dhcpd_unix_group: dhcpd diff --git a/vars/RedHat.yml b/vars/RedHat.yml new file mode 100644 index 0000000..db1bd2a --- /dev/null +++ b/vars/RedHat.yml @@ -0,0 +1,13 @@ +--- + +dhcpd_main_config: /etc/dhcp/dhcpd.conf + +dhcpd_cache_directory: /var/lib/dhcp + +dhcpd_package_names: +- dhcp-server + +dhcpd_service_name: dhcpd + +dhcpd_unix_user: dhcpd +dhcpd_unix_group: dhcpd