Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,14 @@ jobs:
run: ./setup-environment
- name: Start VMs
run: |
./forge vms start --vms "quadlet client ${{ matrix.database == 'external' && 'database' || '' }}"
./forge vms start --vms "quadlet client named ${{ matrix.database == 'external' && 'database' || '' }}"
- name: Configure remote-database
if: matrix.database == 'external'
run: |
./forge remote-database
- name: Configure remote-named
run: |
./forge remote-named
- name: Configure repositories
run: |
./forge setup-repositories
Expand Down Expand Up @@ -173,6 +176,8 @@ jobs:
--add-feature ansible \
--add-feature bmc \
--add-feature webhooks \
--add-feature dns \
--dns-provider nsupdate --dns-server named.example.com --dns-nsupdate-keyfile $(pwd)/.var/lib/foremanctl/rndc.key \
${{ matrix.iop == 'enabled' && '--add-feature iop' || '' }}
- name: Run tests
run: |
Expand Down Expand Up @@ -349,7 +354,10 @@ jobs:
run: ./setup-environment
- name: Start VMs
run: |
./forge vms start --vms "quadlet client"
./forge vms start --vms "quadlet client named"
- name: Configure remote-named
run: |
./forge remote-named
- name: Configure repositories
run: |
./forge setup-repositories
Expand Down Expand Up @@ -377,7 +385,9 @@ jobs:
--add-feature bmc \
--add-feature google \
--add-feature remote-execution \
--add-feature webhooks
--add-feature webhooks \
--add-feature dns \
--dns-provider nsupdate --dns-server named.example.com --dns-nsupdate-keyfile $(pwd)/.var/lib/foremanctl/rndc.key
- name: Run tests
run: |
./forge test --pytest-args="--featureset=migration"
Expand Down Expand Up @@ -552,7 +562,10 @@ jobs:
run: cp -a vendor_overrides/satellite src/playbooks/_vendor_overrides
- name: Start VMs
run: |
./forge vms start --vms "quadlet client"
./forge vms start --vms "quadlet client named"
- name: Configure remote-named
run: |
./forge remote-named
- name: Configure repositories
run: |
./forge setup-repositories
Expand All @@ -573,7 +586,9 @@ jobs:
- name: Deploy features
run: |
./foremanctl deploy \
--add-feature bmc
--add-feature bmc \
--add-feature dns \
--dns-provider nsupdate --dns-server named.example.com --dns-nsupdate-keyfile $(pwd)/.var/lib/foremanctl/rndc.key \
- name: Run tests
run: |
./forge test --pytest-args="--featureset=satellite"
Expand Down
10 changes: 10 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ Vagrant.configure("2") do |config|
end
end

config.vm.define "named" do |override|
override.vm.box = ENV.fetch("FOREMANCTL_BASE_BOX", "centos/stream10")
set_centos_box_url(override.vm)
override.vm.hostname = "named.#{DOMAIN}"

override.vm.provider "libvirt" do |libvirt, provider|
libvirt.memory = 2048
end
end

# Load user-local box definitions from boxes.yaml (gitignored)
boxes_yaml = File.join(__dir__, 'boxes.yaml')
if File.exist?(boxes_yaml)
Expand Down
2 changes: 2 additions & 0 deletions development/playbooks/remote-named/metadata.obsah.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
help: Setup a machine with BIND
13 changes: 13 additions & 0 deletions development/playbooks/remote-named/remote-named.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
- name: Setup remote named
hosts:
- named
become: true
roles:
- role: bind
tasks:
- name: Fetch rndc key
ansible.builtin.fetch:
src: "/etc/named/rndc.key"
dest: "{{ obsah_state_path }}/rndc.key"
flat: true
1 change: 1 addition & 0 deletions development/playbooks/test/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
ansible.builtin.package:
name:
- nmap
- bind-utils

- name: Execute tests
gather_facts: false
Expand Down
9 changes: 9 additions & 0 deletions development/roles/bind/files/empty.zone
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
$TTL 2d ; default TTL for zone
@ IN SOA @ hostmaster.invalid. (
0 ; serial number
12h ; refresh
15m ; update retry
3w ; expiry
2h ; minimum
)
IN NS localhost.
69 changes: 69 additions & 0 deletions development/roles/bind/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
- name: Install BIND
ansible.builtin.package:
name:
- bind
- bind-utils
state: present

- name: Generate the rndc key
ansible.builtin.command:
cmd: rndc-confgen -a -c /etc/named/rndc.key
creates: /etc/named/rndc.key

- name: Set permissions on rndc key
ansible.builtin.file:
path: /etc/named/rndc.key
owner: root
group: named
mode: '0640'

- name: Copy the base zone files
ansible.builtin.copy:
src: empty.zone
dest: "/var/named/{{ item }}.db"
owner: root
group: named
mode: '0640'
loop:
- example.test
- 2.0.192.in-addr.arpa
- 8.b.d.0.1.0.0.2.ip6.arpa

- name: Configure example.test zone
ansible.builtin.blockinfile:
path: /etc/named.conf
block: |
include "/etc/named/rndc.key";
zone "example.test" {
type primary;
file "example.test.db";
allow-update { key "rndc-key"; };
};
zone "2.0.192.in-addr.arpa" {
type primary;
file "2.0.192.in-addr.arpa.db";
allow-update { key "rndc-key"; };
};
zone "8.b.d.0.1.0.0.2.ip6.arpa" {
type primary;
file "8.b.d.0.1.0.0.2.ip6.arpa.db";
allow-update { key "rndc-key"; };
};

- name: Configure BIND to listen on any IP
ansible.builtin.lineinfile:
path: /etc/named.conf
regexp: '^(\s+{{ item }})'
line: '\g<1> { any; };'
backrefs: true
loop:
- listen-on port 53
- listen-on-v6 port 53
- allow-query

- name: Start BIND
ansible.builtin.service:
name: named
state: started
enabled: true
10 changes: 5 additions & 5 deletions docs/user/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ There are multiple use cases from the users perspective that dictate what parame
| `--templates-url` | URL that hosts will use to contact the proxy for provisioning templates | `--foreman-proxy-templates-url` |
| `--add-feature registration` | Enable Registration feature | `--foreman-proxy-registration` |
| `--registration-url` | URL that hosts use to reach the registration endpoint | `--foreman-proxy-registration-url` |
| `--add-feature dns` | Enable DNS feature | `--foreman-proxy-dns` |
| `--dns-provider` | Select DNS provider | `--foreman-proxy-dns-provider` |
| `--dns-server` | Configure the target DNS server | `--foreman-proxy-dns-server` |
| `--dns-nsupdate-keyfile` | Configure the key for the target DNS server | `--foreman-proxy-keyfile` |

### Unmapped

Expand All @@ -166,6 +170,7 @@ There are multiple use cases from the users perspective that dictate what parame
| `--foreman-proxy-oauth-consumer-key` | OAuth consumer key for Smart Proxy | Not required(Managed automatically via auth bundle) |
| `--foreman-proxy-oauth-consumer-secret` | OAuth consumer secret for Smart Proxy | Not required(Managed automatically via auth bundle) |
| `--foreman-proxy-templates-listen-on` | Templates proxy to listen on https, http, or both | No longer supported |
| `--foreman-proxy-dns-managed` | Installer managed DNS | not supported |

### Undetermined

Expand All @@ -184,11 +189,6 @@ There are multiple use cases from the users perspective that dictate what parame
| `--foreman-proxy-dhcp-server` | | foreman_proxy | dhcp_server |
| `--foreman-proxy-libvirt-network` | | foreman_proxy | libvirt_network |
| `--foreman-proxy-libvirt-url` | | foreman_proxy | libvirt_url |
| `--foreman-proxy-dns` | | foreman_proxy | dns |
| `--foreman-proxy-dns-managed` | | foreman_proxy | dns_managed |
| `--foreman-proxy-dns-provider` | | foreman_proxy | foreman_proxy::dns_provider |
| `--foreman-proxy-dns-server` | | foreman_proxy | foreman_proxy::dns_server |
| `--foreman-proxy-keyfile` | | foreman_proxy | foreman_proxy::keyfile |
| `--foreman-proxy-plugin-dns-powerdns-rest-api-key` | | foreman_proxy::plugin::dns_powerdns | rest_api_key |
| `--foreman-proxy-plugin-dns-powerdns-rest-url` | | foreman_proxy::plugin::dns_powerdns | rest_url |
| `--foreman-proxy-plugin-dns-route53-aws-access-key` | | foreman_proxy::plugin::dns_route53 | aws_access_key |
Expand Down
4 changes: 4 additions & 0 deletions src/features.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,7 @@ theme-satellite:
internal: true
foreman:
plugin_name: foreman_theme_satellite
dns:
description: DNS management
foreman_proxy:
plugin_name: dns
18 changes: 18 additions & 0 deletions src/playbooks/_foreman_proxy/metadata.obsah.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,21 @@ variables:
foreman_proxy_registration_url:
parameter: --registration-url
help: URL that hosts use to reach the registration endpoint (e.g. https://loadbalancer.example.com).
foreman_proxy_dns_provider:
parameter: --dns-provider
help: DNS provider to use.
choices:
- nsupdate
foreman_proxy_dns_nsupdate_keyfile:
parameter: --dns-nsupdate-keyfile
help: Key file to be used to authenticate with the DNS server
type: AbsolutePath
foreman_proxy_dns_server:
parameter: --dns-server
help: Hostname of the DNS server to communicate with
type: FQDN

constraints:
required_in_list:
- [[[features, dns]], [foreman_proxy_dns_provider]]
- [[[features, dns], [foreman_proxy_dns_provider, nsupdate]], [foreman_proxy_dns_nsupdate_keyfile, foreman_proxy_dns_server]]
7 changes: 7 additions & 0 deletions src/roles/foreman_proxy/defaults/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,10 @@ foreman_proxy_bmc_ipmi_implementation: ipmitool
foreman_proxy_bmc_redfish_verify_ssl: true

foreman_proxy_with_pulp_mirror: "{{ pulp_mirror | default(false) }}"

# DNS settings
foreman_proxy_dns_provider_list:
- dns_nsupdate
foreman_proxy_dns_provider: "{{ undef(hint='You must specify a DNS provider to use') }}"
foreman_proxy_dns_provider_name: "dns_{{ foreman_proxy_dns_provider }}"
foreman_proxy_dns_ttl: 86400
7 changes: 7 additions & 0 deletions src/roles/foreman_proxy/tasks/feature/dns.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
- name: Include tasks for {{ item }}
ansible.builtin.include_tasks: feature.yaml
vars:
feature_enabled: "{{ foreman_proxy_dns_provider_name == item }}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also look at the dns feature being enabled?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coderabbit (in a nitpick) pointed out that this is now a boolean, while the original intent of the variable was to map the whole spectrum of true/false/http/https that foreman proxy supports and with a boolean the != 'false' will be wrong. Sounds like a very valid concern to me, will think about it.

(Mostly commenting so it's not lost in the rabbit hole, hah)

feature_name: "{{ item }}"
loop: "{{ foreman_proxy_dns_provider_list }}"
22 changes: 22 additions & 0 deletions src/roles/foreman_proxy/tasks/feature/dns_nsupdate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
- name: Create RNDC Key podman secret
containers.podman.podman_secret:
state: present

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking it a step further, this should probably look at the enabled state too. Ideally we would clean up items (secrets, systemd drop-ins).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now this file is not included when the feature is disabled, but we certainly can extend this.

name: foreman_proxy-dns_nsupdate-rndc_key
data: "{{ lookup('ansible.builtin.file', foreman_proxy_dns_nsupdate_keyfile) }}"
notify:
- Restart Foreman Proxy
- Refresh Foreman Proxy
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

- name: Mount RNDC key
ansible.builtin.copy:
dest: /etc/containers/systemd/foreman-proxy.container.d/dns_nsupdate-rndc_key.conf
content: |
[Container]
Secret=foreman_proxy-dns_nsupdate-rndc_key,type=mount,target=/etc/foreman-proxy/rndc.key
mode: '0644'
owner: root
group: root
notify:
- Restart Foreman Proxy
- Refresh Foreman Proxy
5 changes: 5 additions & 0 deletions src/roles/foreman_proxy/templates/settings.d/dns.yml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
:enabled: {{ feature_enabled }}

:use_provider: {{ foreman_proxy_dns_provider_name }}
:dns_ttl: {{ foreman_proxy_dns_ttl }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
:dns_key: /etc/foreman-proxy/rndc.key
:dns_server: {{ foreman_proxy_dns_server }}
53 changes: 53 additions & 0 deletions tests/feature/foreman-proxy/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,56 @@ def test_registration_url(obsah_params):
def test_registration_endpoint(proxy_v2_features):
assert 'registration' in proxy_v2_features
assert proxy_v2_features['registration'].get('state') == 'running'


@pytest.mark.feature('dns')
def test_dns_provider(proxy_v2_features):
settings = proxy_v2_features['dns'].get('settings', {})
assert settings.get('use_provider') == 'dns_nsupdate'


@pytest.mark.feature('dns')
@pytest.mark.parametrize('dns_name,dns_value,dns_type', [
('test-v4.example.test', '192.0.2.100', 'A'),
('test-v6.example.test', '2001:db8::1', 'AAAA'),
('test-cname.example.test', 'test.example.test', 'CNAME'),
('reverse-v4.example.test', '100.2.0.192.in-addr.arpa', 'PTR'),
('reverse-v6.example.test', '0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa', 'PTR')
])
def test_dns_nsupdate(server, certificates, server_fqdn, dns_name, dns_value, dns_type):

def dns_cmd(curl_opts, extra_url=""):
return server.run(
f"curl --cacert {certificates['server_ca_certificate']} "
f"--cert {certificates['client_certificate']} "
f"--key {certificates['client_key']} "
f"--output /dev/null --write-out '%{{http_code}}' "
f"{curl_opts} "
f"https://{server_fqdn}:8443/dns/{extra_url}"
)

if dns_type == 'PTR':
expected = f"{dns_name}."
query = dns_value
elif dns_type == 'CNAME':
expected = f"{dns_value}."
query = dns_name
else:
expected = dns_value
query = dns_name

create_cmd = dns_cmd(f"--data 'fqdn={dns_name}&value={dns_value}&type={dns_type}'")
assert create_cmd.succeeded
assert create_cmd.stdout == '200'

verify_cmd = server.run(f"dig +short {query} {dns_type} @named.example.com")
assert verify_cmd.succeeded
assert verify_cmd.stdout.strip() == expected

delete_cmd = dns_cmd("-X DELETE", f"{query}/{dns_type}")
assert delete_cmd.succeeded
assert delete_cmd.stdout == '200'

verify_cmd = server.run(f"dig +short {query} {dns_type} @named.example.com")
assert verify_cmd.succeeded
assert verify_cmd.stdout.strip() == ""
3 changes: 2 additions & 1 deletion tests/features_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
'content/deb',
'content/python',
'content/rpm',
'dns',
'dynflow',
'foreman',
'foreman-proxy',
Expand All @@ -29,7 +30,7 @@
EXPECTED_FEATURES = {
'default': DEFAULT_FEATURES,
'default-iop': DEFAULT_FEATURES | {'iop', 'rh-cloud'},
'upgrade': (DEFAULT_FEATURES | {'iop', 'rh-cloud'}) - {'ansible', 'webhooks'},
'upgrade': (DEFAULT_FEATURES | {'iop', 'rh-cloud'}) - {'ansible', 'dns', 'webhooks'},
'migration': DEFAULT_FEATURES,
'proxy': {
'bmc',
Expand Down
Loading