--- # Download all the tools, set up registry credentials, ssh keys, and ensure the health of a DHCP and a DNS server on utility. # # XXX: If someone has gone beyond this point in the course and runs this playbook, it will revert the changes back to the original. # - name: Download all the tools we need on workstation, set up registry credentials, and a SSH keypair. hosts: workstation.lab.example.com gather_subset: min become: no vars: downloads: - baseurl: https://mirror.openshift.com/pub/openshift-v4/clients/butane/latest filename: butane-amd64 dest_dir: /usr/local/bin deploy: yes extract: no extract_files: [] target_filename: butane completion: no - baseurl: https://mirror.openshift.com/pub/openshift-v4/clients/coreos-installer/latest filename: coreos-installer_amd64 dest_dir: /usr/local/bin deploy: yes extract: no extract_files: [] target_filename: coreos-installer completion: no - baseurl: https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.18.6 filename: openshift-install-rhel9-amd64.tar.gz dest_dir: /usr/local/bin deploy: yes extract: yes extract_files: - openshift-install-fips target_filename: None completion: yes - baseurl: https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable-4.18 filename: openshift-client-linux-amd64-rhel9.tar.gz dest_dir: /usr/local/bin deploy: yes extract: yes extract_files: - oc - kubectl target_filename: None completion: yes - baseurl: https://rhcos.mirror.openshift.com/art/storage/prod/streams/4.18-9.4/builds/418.94.202501221327-0/x86_64 filename: rhcos-418.94.202501221327-0-live.x86_64.iso deploy: no tasks: - name: Download tools, if necessary. ansible.builtin.get_url: url: "{{ item.baseurl }}/{{ item.filename }}" dest: "{{ ansible_facts['user_dir'] }}/Downloads/{{ item.filename }}" mode: 0644 owner: student group: student loop: "{{ downloads }}" loop_control: label: "{{ item.filename }}" - name: Extract tools, if necessary. become: yes ansible.builtin.unarchive: src: "{{ ansible_facts['user_dir'] }}/Downloads/{{ item.filename }}" remote_src: yes dest: "{{ item.dest_dir }}" include: "{{ item.extract_files }}" creates: "{{ item.extract_files[0] }}" mode: 0755 owner: root group: root loop: "{{ downloads }}" loop_control: label: "{{ item.filename }}" when: - item.deploy - item.extract - name: Install tools, if necessary. become: yes ansible.builtin.copy: src: "{{ ansible_facts['user_dir'] }}/Downloads/{{ item.filename }}" remote_src: yes dest: "{{ item.dest_dir }}/{{ item.target_filename }}" mode: 0755 owner: root group: root loop: "{{ downloads }}" loop_control: label: "{{ item.filename }}" when: - item.deploy - not item.extract - item.target_filename is defined - item.target_filename != None - name: Create command completion files, if necessary. become: yes ansible.builtin.shell: cmd: "{{ item.extract_files[0] }} completion bash > /etc/bash_completion.d/{{ item.extract_files[0] }}.completion" creates: "/etc/bash_completion.d/{{ item.extract_files[0] }}.completion" loop: "{{ downloads }}" loop_control: label: "{{ item.filename }}" when: - item.completion is defined - item.completion - name: Ensure .docker directory exists. ansible.builtin.file: path: "{{ ansible_facts['user_dir'] }}/.docker" state: directory mode: 0750 owner: student group: student - name: Ensure mirror registry auth file is on standby. ansible.builtin.copy: dest: "{{ ansible_facts['user_dir'] }}/.docker/config.json-mirror" mode: 0640 owner: student group: student content: '{"auths":{"registry.ocp4.example.com":{"auth":"YWRtaW46cmVkaGF0MTIz"},"cloud.openshift.com":{"auth":"b3BlbnNoaWZ0LXJlbGVhc2UtZGV2K29jbV9hY2Nlc3NfNGM4ZmZhZTI5ZjUzNGJiZjgyZDhlNWE0ZmZiYjRiY2Y6N0NER083UjM4TE1KTEJTN1EzVkVKQVkyTVVCUkpXQjNWNlUxR1BLVzRaN0tGTVpaSENVVTMwMVdaTzMxTDBPNQ==","email":"glsbugs-devops@redhat.com"},"quay.io":{"auth":"b3BlbnNoaWZ0LXJlbGVhc2UtZGV2K29jbV9hY2Nlc3NfNGM4ZmZhZTI5ZjUzNGJiZjgyZDhlNWE0ZmZiYjRiY2Y6N0NER083UjM4TE1KTEJTN1EzVkVKQVkyTVVCUkpXQjNWNlUxR1BLVzRaN0tGTVpaSENVVTMwMVdaTzMxTDBPNQ==","email":"glsbugs-devops@redhat.com"},"registry.connect.redhat.com":{"auth":"fHVoYy1wb29sLTlmMDA1Mzc2LTM2YTItNDJhMS1hNTQwLTA0NzNkYzg3MzYzMzpleUpoYkdjaU9pSlNVelV4TWlKOS5leUp6ZFdJaU9pSTVPRGc1WVdFeFl6Qm1PV0kwWmpVM1lqazNObUk1WldFeU16SXdaalUwTUNKOS5zWmQ5VE1RbzBXREc2NUc5Qk1ObmtuYlBjRkIzNmhyRFhkMThfdTNLeHFaczdlOG1hQ19QeEFReGpwdVk0YVM2VERIbkxDNWpGYjRRNXFYVEpWbjJCOGE4cDFuY08tM24ySG5QdDg3NmktVUFDU3lldWtpb3k4aHI0V3d1ZkhReFVYMmxxWFhYdjN6blE3am1URUNBc25rWkNRSFU1dFNpRnNUZHhFZGZkeU42Z20xN3VqY2thZG5NbFBZcTZfU1I2bUtLaUpUdFQ3SFlDWXJBVk5zZ0tfNGFkZ2MtRXBlbEtHbGNERWkzNGhYbzFqbEIzRERyUWkxSUxCV0UwZkdXb1czZy1ZUzFGMFlEXzc0bm1XSU5mUE1jM25UOERaQWl0OEw0VlFPTnZnUE51YnVfTVVGUGhqX29VUjF3VUR0a1BRNktJdm82UWYyRkdwMndLM1B6YnRBRFFzRVZTZDlITzQ3a0RKdGFobk95YTFmRmdqZVk1bFNxLW1vT2RqUldCZ3U2XzNIX25lZExJR1lQRHRBZnp5cGJ1eHZ1cEd1M2hYWnVzeWN0aURtR203SkR5RW5KdjF1RFZmYVduU2EzSV9NcFRSVVcyZWU1RF9CanJleTdlU2I0bEpGcmp1eC1nY2JVaHFsWGJZc2l6azdXWHpvRmtrVFlMdXFDQ1FvS1J0OFdSN1UzTmh3c3Q2ckV3eEFOaWJFTlNzUVB3MGg4X0NDRm5qTHFSTl82cWpTc0tpeWRGT2tHVFliT0taTktaSVVhYkZFTjRhYVRVYmlYTVdPS2Eyak1xLUhwazBMNEowUmtOM2JkQVVqWmtERHE0ZFY1ZVFjdXNIeV9LY29nd1VKSjZ4MDNObnM4b0xBdjRJZ3RKeXlxcmE1YUJHSkxReHNjRXVSNzQwWQ==","email":"glsbugs-devops@redhat.com"},"registry.redhat.io":{"auth":"fHVoYy1wb29sLTlmMDA1Mzc2LTM2YTItNDJhMS1hNTQwLTA0NzNkYzg3MzYzMzpleUpoYkdjaU9pSlNVelV4TWlKOS5leUp6ZFdJaU9pSTVPRGc1WVdFeFl6Qm1PV0kwWmpVM1lqazNObUk1WldFeU16SXdaalUwTUNKOS5zWmQ5VE1RbzBXREc2NUc5Qk1ObmtuYlBjRkIzNmhyRFhkMThfdTNLeHFaczdlOG1hQ19QeEFReGpwdVk0YVM2VERIbkxDNWpGYjRRNXFYVEpWbjJCOGE4cDFuY08tM24ySG5QdDg3NmktVUFDU3lldWtpb3k4aHI0V3d1ZkhReFVYMmxxWFhYdjN6blE3am1URUNBc25rWkNRSFU1dFNpRnNUZHhFZGZkeU42Z20xN3VqY2thZG5NbFBZcTZfU1I2bUtLaUpUdFQ3SFlDWXJBVk5zZ0tfNGFkZ2MtRXBlbEtHbGNERWkzNGhYbzFqbEIzRERyUWkxSUxCV0UwZkdXb1czZy1ZUzFGMFlEXzc0bm1XSU5mUE1jM25UOERaQWl0OEw0VlFPTnZnUE51YnVfTVVGUGhqX29VUjF3VUR0a1BRNktJdm82UWYyRkdwMndLM1B6YnRBRFFzRVZTZDlITzQ3a0RKdGFobk95YTFmRmdqZVk1bFNxLW1vT2RqUldCZ3U2XzNIX25lZExJR1lQRHRBZnp5cGJ1eHZ1cEd1M2hYWnVzeWN0aURtR203SkR5RW5KdjF1RFZmYVduU2EzSV9NcFRSVVcyZWU1RF9CanJleTdlU2I0bEpGcmp1eC1nY2JVaHFsWGJZc2l6azdXWHpvRmtrVFlMdXFDQ1FvS1J0OFdSN1UzTmh3c3Q2ckV3eEFOaWJFTlNzUVB3MGg4X0NDRm5qTHFSTl82cWpTc0tpeWRGT2tHVFliT0taTktaSVVhYkZFTjRhYVRVYmlYTVdPS2Eyak1xLUhwazBMNEowUmtOM2JkQVVqWmtERHE0ZFY1ZVFjdXNIeV9LY29nd1VKSjZ4MDNObnM4b0xBdjRJZ3RKeXlxcmE1YUJHSkxReHNjRXVSNzQwWQ==","email":"glsbugs-devops@redhat.com"}}}' - name: Ensure installation registry auth file is active. ansible.builtin.copy: dest: "{{ item }}" mode: 0640 owner: student group: student content: '{"auths":{"registry.ocp4.example.com":{"auth":"YWRtaW46cmVkaGF0MTIz"}}}' loop: - "{{ ansible_facts['user_dir'] }}/.docker/config.json" - "{{ ansible_facts['user_dir'] }}/install-pull-secret" - name: Create a SSH keypair, if necessary. community.crypto.openssh_keypair: path: "{{ ansible_facts['user_dir'] }}/.ssh/openshift" type: rsa size: 2048 state: present - name: Ensure DHCP and DNS servers on utility are configured. hosts: utility.lab.example.com gather_subset: min become: yes tasks: - name: Ensure there is a DHCP server installed. ansible.builtin.yum: name: dhcp-server state: present - name: Fix the environment of the DHCP server a bit by ensuring the unit file specifies it. ansible.builtin.copy: dest: /etc/systemd/system/dhcpd.service mode: 0644 owner: root group: root content: | [Unit] Description=DHCPv4 Server Daemon Documentation=man:dhcpd(8) man:dhcpd.conf(5) Wants=network-online.target After=network-online.target After=time-sync.target [Service] Type=notify Environment=DHCPDARGS=eth1 EnvironmentFile=-/etc/sysconfig/dhcpd ExecStart=/usr/sbin/dhcpd -f -cf /etc/dhcp/dhcpd.conf -user dhcpd -group dhcpd --no-pid $DHCPDARGS StandardError=null [Install] WantedBy=multi-user.target notify: reload systemd - name: Ensure systemd is reloaded if it needs to be at this point. ansible.builtin.meta: flush_handlers - name: Ensure the DHCP config file has the correct content. ansible.builtin.copy: dest: /etc/dhcp/dhcpd.conf mode: 0640 owner: root group: root content: | ddns-update-style interim; ignore client-updates; authoritative; allow booting; allow bootp; allow unknown-clients; # Set default and max IP lease time to infinite with -1 value default-lease-time -1; max-lease-time -1; # BEGIN ANSIBLE MANAGED DHCP CONFIG for ocp4.example.com subnet 192.168.50.0 netmask 255.255.255.0 { range 192.168.50.100 192.168.50.149; option routers 192.168.50.254; option ntp-servers 103.16.182.23,103.16.182.214; option domain-search "ocp4.example.com"; filename "pxelinux.0"; option domain-name-servers 192.168.50.254; next-server 192.168.50.254; host master01.ocp4.example.com { hardware ethernet 52:54:00:00:32:0A; fixed-address 192.168.50.10; option host-name "master01"; } host master02.ocp4.example.com { hardware ethernet 52:54:00:00:32:0B; fixed-address 192.168.50.11; option host-name "master02"; } host master03.ocp4.example.com { hardware ethernet 52:54:00:00:32:0C; fixed-address 192.168.50.12; option host-name "master03"; } host worker01.ocp4.example.com { hardware ethernet 52:54:00:00:32:0D; fixed-address 192.168.50.13; option host-name "worker01"; } host worker02.ocp4.example.com { hardware ethernet 52:54:00:00:32:0E; fixed-address 192.168.50.14; option host-name "worker02"; } } # END ANSIBLE MANAGED DHCP CONFIG for ocp4.example.com notify: restart dhcpd - name: Ensure DHCP server is enabled and running. ansible.builtin.systemd_service: name: dhcpd enabled: yes state: started - name: Ensure the Bind config file has the correct content. ansible.builtin.copy: dest: /etc/named.conf mode: 0640 owner: root group: root content: | // // named.conf // // Provided by Red Hat bind package to configure the ISC BIND named(8) DNS // server as a caching only nameserver (as a localhost DNS resolver only). // // See /usr/share/doc/bind*/sample/ for example named configuration files. // options { #listen-on port 53 { 127.0.0.1; }; #listen-on-v6 port 53 { ::1; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; secroots-file "/var/named/data/named.secroots"; recursing-file "/var/named/data/named.recursing"; allow-query { localhost; 192.168.50.0/24; 172.25.250.254; }; /* - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion. - If you are building a RECURSIVE (caching) DNS server, you need to enable recursion. - If your recursive DNS server has a public IP address, you MUST enable access control to limit queries to your legitimate users. Failing to do so will cause your server to become part of large scale DNS amplification attacks. Implementing BCP38 within your network would greatly reduce such attack surface */ recursion yes; dnssec-enable no; dnssec-validation no; managed-keys-directory "/var/named/dynamic"; geoip-directory "/usr/share/GeoIP"; pid-file "/run/named/named.pid"; session-keyfile "/run/named/session.key"; # BEGIN ANSIBLE MANAGED FORWARDERS forwarders { 172.25.250.254; }; # END ANSIBLE MANAGED FORWARDERS /* https://fedoraproject.org/wiki/Changes/CryptoPolicy */ include "/etc/crypto-policies/back-ends/bind.config"; }; logging { channel default_debug { file "data/named.run"; severity dynamic; }; }; zone "." IN { type hint; file "named.ca"; }; include "/etc/named.rfc1912.zones"; include "/etc/named.root.key"; # BEGIN ANSIBLE MANAGED DNS ZONE for ocp4.example.com zone "ocp4.example.com" { type master; file "ocp4.example.com.db"; allow-update { none; }; }; # END ANSIBLE MANAGED DNS ZONE for ocp4.example.com # BEGIN ANSIBLE MANAGED DNS REVERSE ZONE for ocp4.example.com zone "50.168.192.in-addr.arpa" IN { type master; file "ocp4.example.com.reverse.db"; allow-update { none; }; }; notify: restart named - name: Ensure the forward lookup zone file has the correct content. ansible.builtin.copy: dest: /var/named/ocp4.example.com.db mode: 0644 owner: root group: root content: | $TTL 1D @ IN SOA dns.ocp4.example.com. root.example.com. ( 2019022400 ; serial 3h ; refresh 15 ; retry 1w ; expire 3h ; minimum ) IN NS dns.ocp4.example.com. dns IN A 192.168.50.254 api IN A 192.168.50.254 api-int IN A 192.168.50.254 registry IN A 192.168.50.50 git IN A 192.168.50.50 *.apps IN A 192.168.50.254 master01 IN A 192.168.50.10 master02 IN A 192.168.50.11 master03 IN A 192.168.50.12 worker01 IN A 192.168.50.13 worker02 IN A 192.168.50.14 idm IN A 192.168.50.40 notify: restart named - name: Ensure the reverse lookup zone file has the correct content. ansible.builtin.copy: dest: /var/named/ocp4.example.com.reverse.db mode: 0644 owner: root group: root content: | $TTL 1D @ IN SOA dns.ocp4.example.com. root.example.com. ( 2019022400 ; serial 3h ; refresh 15 ; retry 1w ; expire 3h ; minimum ) IN NS dns.ocp4.example.com. 254 IN PTR api.ocp4.example.com. 254 IN PTR api-int.ocp4.example.com. 50 IN PTR registry.ocp4.example.com. 50 IN PTR git.ocp4.example.com. 10 IN PTR master01.ocp4.example.com. 11 IN PTR master02.ocp4.example.com. 12 IN PTR master03.ocp4.example.com. 13 IN PTR worker01.ocp4.example.com. 14 IN PTR worker02.ocp4.example.com. 40 IN PTR idm.ocp4.example.com. notify: restart named - name: Ensure Bind server is enabled and running. ansible.builtin.systemd_service: name: named enabled: yes state: started handlers: - name: restart dhcpd ansible.builtin.systemd_service: name: dhcpd state: restarted - name: restart named ansible.builtin.systemd_service: name: named state: restarted - name: reload systemd ansible.builtin.systemd_service: daemon_reload: true - name: Have utility serve time. hosts: utility.lab.example.com become: no gather_subset: min tasks: - name: Ensure we have the correct chrony.conf become: yes ansible.builtin.copy: dest: /etc/chrony.conf mode: 0644 content: | # Use public servers from the pool.ntp.org project. # Please consider joining the pool (http://www.pool.ntp.org/join.html). server 172.25.254.254 iburst # Record the rate at which the system clock gains/losses time. driftfile /var/lib/chrony/drift # Allow the system clock to be stepped in the first three updates # if its offset is larger than 1 second. makestep 1.0 3 # Enable kernel synchronization of the real-time clock (RTC). rtcsync # Enable hardware timestamping on all interfaces that support it. #hwtimestamp * # Increase the minimum number of selectable sources required to adjust # the system clock. #minsources 2 # Allow NTP client access from local network. #allow 192.168.0.0/16 allow all bindcmdaddress 0.0.0.0 cmdallow all # Serve time even if not synchronized to a time source. #local stratum 10 # Specify file containing keys for NTP authentication. keyfile /etc/chrony.keys # Get TAI-UTC offset and leap seconds from the system tz database. leapsectz right/UTC # Specify directory for log files. logdir /var/log/chrony # Select which information is logged. #log measurements statistics tracking notify: - restart chronyd - name: Ensure firewall allows NTP. become: yes ansible.posix.firewalld: immediate: yes permanent: yes zone: "{{ item }}" service: ntp state: enabled loop: - external - public - name: Ensure firewall allows cmdport. become: yes ansible.posix.firewalld: immediate: yes permanent: yes zone: "{{ item }}" port: 323/udp state: enabled loop: - external - public handlers: - name: restart chronyd become: yes ansible.builtin.service: name: chronyd state: restarted ...