add server_iso role

This commit is contained in:
Frank Adaemmer 2022-10-16 10:44:17 +02:00
parent e60a01d410
commit 35887bc7a0
12 changed files with 358 additions and 0 deletions

1
roles/server_iso/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
files/*.iso

View file

@ -0,0 +1,31 @@
# server_iso Role
Create an Oracle Linux 9 ISO for automatic server installation.
## Variables
<!-- BEGIN Argument Specs -->
|Name |Type |Requiered |Description |
|------|------|-----------|-------------|
|src_iso_download_url |str | no | Download link to source installation medium |
|src_iso_path |str | no | Storage location of downloaded source installation medium |
|src_iso_checksum |str | no | Checksum of downloaded source installation medium |
|src_iso_label |str | no | Volume ID of installation medium. Could be displayed by `xorriso -indev {{ role_path }}/files/OracleLinux-R9-U0-x86_64-boot-uek.iso -toc` |
|reboot_after_installation |bool | no | Automatic reboot after installation. |
|gateway |str | no | IPv4 default gateway address. This will only be used when ansible_host is a IP address. |
|nameserver |str | no | IPv4 nameserver address. This will only be used when ansible_host is a IP address. |
|netmask |str | no | IPv4 subnet mask. This will only be used when ansible_host is a IP address. |
|ssh_keys |list[str] | no | List of ssh public keys that will be added to .ssh/authorized_keys |
|iso_path |str | yes | Storage location for the created ISO |
<!-- END Argument Specs -->
## Example Playbook
```yaml
- name: Create server ISO
hosts: server
gather_facts: false
vars:
iso_path: "~/Downloads/OEL_{{ inventory_hostname }}.iso"
ssh_keys:
- "ssh-rsa 8J+OtU5ldmVyIGdvbm5hIGdpdmUgeW91IHVw8J+Otg== UmljayDwn5W6@IPCfp7sg"
roles:
- server_iso
```

View file

@ -0,0 +1,6 @@
---
src_iso_download_url: https://yum.oracle.com/ISOS/OracleLinux/OL9/u0/x86_64/OracleLinux-R9-U0-x86_64-boot-uek.iso
src_iso_path: "{{ role_path }}/files/OracleLinux-R9-U0-x86_64-boot-uek.iso"
src_iso_checksum: sha256:a782e8c78a629ab1c19fcb32e76d3b81c7ef1b04060a0465253c103686339f3a
src_iso_label: OL-9-0-0-BaseOS-x86_64 # xorriso -indev ~/sync/kestrel-pronghorn/ansible/roles/server_iso/files/OracleLinux-R9-U0-x86_64-boot-uek.iso -toc
reboot_after_installation: false

View file

View file

@ -0,0 +1,15 @@
---
- name: Set mode
ansible.builtin.file:
path: "{{ tmp_iso_path['path'] }}"
state: directory
mode: 0744
recurse: true
listen: Server ISO cleanup
delegate_to: localhost
- name: Server ISO cleanup
ansible.builtin.file:
path: "{{ tmp_iso_path['path'] }}"
state: absent
delegate_to: localhost

View file

@ -0,0 +1,60 @@
---
argument_specs:
main:
short_description: Create an ISO for server installation
description: Create an Oracle Linux 9 ISO for automatic server installation.
options:
# line 2 of defaults/main.yml
src_iso_download_url:
default: "https://yum.oracle.com/ISOS/OracleLinux/OL9/u0/x86_64/OracleLinux-R9-U0-x86_64-boot-uek.iso"
description: "Download link to source installation medium"
type: "str"
# line 3 of defaults/main.yml
src_iso_path:
default: "{{ role_path }}/files/OracleLinux-R9-U0-x86_64-boot-uek.iso"
description: "Storage location of downloaded source installation medium"
type: "str"
# line 4 of defaults/main.yml
src_iso_checksum:
default: "sha256:a782e8c78a629ab1c19fcb32e76d3b81c7ef1b04060a0465253c103686339f3a"
description: "Checksum of downloaded source installation medium"
type: "str"
# line 5 of defaults/main.yml
src_iso_label:
default: "OL-9-0-0-BaseOS-x86_64"
description: "Volume ID of installation medium. Could be displayed by `xorriso -indev {{ role_path }}/files/OracleLinux-R9-U0-x86_64-boot-uek.iso -toc`"
type: "str"
# line 6 of defaults/main.yml
reboot_after_installation:
default: false
description: "Automatic reboot after installation."
type: "bool"
gateway:
default: "{{ (((ansible_host + '/255.255.255.0') | ansible.utils.ipaddr('network') | ansible.utils.ipaddr('int'))+1) | string | ansible.utils.ipaddr}}"
description: "IPv4 default gateway address. This will only be used when ansible_host is a IP address."
type: "str"
nameserver:
default: "{{ (((ansible_host + '/255.255.255.0') | ansible.utils.ipaddr('network') | ansible.utils.ipaddr('int'))+1) | string | ansible.utils.ipaddr}}"
description: "IPv4 nameserver address. This will only be used when ansible_host is a IP address."
type: "str"
netmask:
default: "255.255.255.0"
description: "IPv4 subnet mask. This will only be used when ansible_host is a IP address."
type: "str"
ssh_keys:
description: "List of ssh public keys that will be added to .ssh/authorized_keys"
type: 'list'
elements: 'str'
iso_path:
required: true
description: "Storage location for the created ISO"
type: "str"

View file

@ -0,0 +1,45 @@
---
galaxy_info:
author: Frank Adaemmer <frank@adaemmer.com>
description: Create an ISO for server installation
# If the issue tracker for your role is not on github, uncomment the
# next line and provide a value
# issue_tracker_url: http://example.com/issue/tracker
# Choose a valid license ID from https://spdx.org - some suggested licenses:
# - BSD-3-Clause (default)
# - MIT
# - GPL-2.0-or-later
# - GPL-3.0-only
# - Apache-2.0
# - CC-BY-4.0
license: GPL-3.0-or-later
min_ansible_version: '2.9'
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
#
# Provide a list of supported platforms, and for each platform a list of versions.
# If you don't wish to enumerate all versions for a particular platform, use 'all'.
# To view available platforms and versions (or releases), visit:
# https://galaxy.ansible.com/api/v1/platforms/
#
platforms:
- name: EL
version:
- '9'
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.

View file

@ -0,0 +1,67 @@
---
- name: Create ISO block
delegate_to: localhost
block:
- name: Create custom kickstart file
ansible.builtin.template:
src: kickstart.ks.j2
dest: "{{ tmp_iso_path['path'] }}/kickstart.ks"
mode: 0644
- name: Add kickstart file to GRUB BIOS
ansible.builtin.replace:
path: "{{ tmp_iso_path['path'] }}/isolinux/isolinux.cfg"
regexp: ^(\s*append .*)
replace: \g<1> inst.ks=hd:LABEL={{ src_iso_label }}:/kickstart.ks
- name: Add kickstart file to GRUB EFI
ansible.builtin.replace:
path: "{{ tmp_iso_path['path'] }}/EFI/BOOT/grub.cfg"
regexp: ^(\s*linuxefi .*)
replace: \g<1> inst.ks=hd:LABEL={{ src_iso_label }}:/kickstart.ks
- name: Decrease timeout BIOS
ansible.builtin.lineinfile:
path: "{{ tmp_iso_path['path'] }}/isolinux/isolinux.cfg"
line: timeout 30
regexp: ^timeout
- name: Remove default BIOS
ansible.builtin.lineinfile:
path: "{{ tmp_iso_path['path'] }}/isolinux/isolinux.cfg"
regexp: ^ menu default
state: absent
- name: Set default BIOS
ansible.builtin.lineinfile:
path: "{{ tmp_iso_path['path'] }}/isolinux/isolinux.cfg"
line: ' menu default'
regexp: ^ menu default
firstmatch: true
insertafter: ^ menu label
- name: Decrease timeout EFI
ansible.builtin.lineinfile:
path: "{{ tmp_iso_path['path'] }}/EFI/BOOT/grub.cfg"
line: set timeout=3
regexp: ^set timeout=
- name: Set default EFI
ansible.builtin.lineinfile:
path: "{{ tmp_iso_path['path'] }}/EFI/BOOT/grub.cfg"
line: set default="0"
regexp: ^set default=
- name: Pack ISO
ansible.builtin.command:
cmd: >
xorrisofs -U -r -v -J -joliet-long -V "{{ src_iso_label }}"
-b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4
-boot-info-table -eltorito-alt-boot -e images/efiboot.img -no-emul-boot
-o "{{ iso_path }}" .
chdir: "{{ tmp_iso_path['path'] }}"
changed_when:
- result['rc'] is defined
- result['rc'] == 0
register: result
- name: Pause
ansible.builtin.pause:
prompt: "Pause"

View file

@ -0,0 +1,8 @@
---
- name: Download ISO
ansible.builtin.get_url:
url: "{{ src_iso_download_url }}"
dest: "{{ src_iso_path }}"
checksum: "{{ src_iso_checksum }}"
mode: 0644
delegate_to: localhost

View file

@ -0,0 +1,20 @@
---
- name: Extract Block
delegate_to: localhost
block:
- name: Create temp dir
ansible.builtin.tempfile:
state: directory
register: tmp_iso_path
notify: Server ISO cleanup
- name: Extract ISO
ansible.builtin.command:
cmd: >
xorriso -osirrox on
-indev {{ src_iso_path }}
-extract / {{ tmp_iso_path['path'] }}
changed_when:
- result['rc'] is defined
- result['rc'] == 0
register: result

View file

@ -0,0 +1,14 @@
---
- name: Assert iso_path
ansible.builtin.assert:
that:
- iso_path is defined
- name: Download ISO
ansible.builtin.import_tasks: download_iso.yml
- name: Extract ISO
ansible.builtin.import_tasks: extract_iso.yml
- name: Create ISO
ansible.builtin.import_tasks: create_iso.yml

View file

@ -0,0 +1,91 @@
skipx
firewall --enabled --ssh
repo --name="AppStream" --baseurl=http://yum.oracle.com/repo/OracleLinux/OL9/appstream/x86_64
repo --name="UEK" --baseurl=http://yum.oracle.com/repo/OracleLinux/OL9/UEKR7/x86_64
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
%addon com_redhat_oscap
content-type = scap-security-guide
datastream-id = scap_org.open-scap_datastream_from_xccdf_ssg-ol9-xccdf-1.2.xml
xccdf-id = scap_org.open-scap_cref_ssg-ol9-xccdf-1.2.xml
profile = xccdf_org.ssgproject.content_profile_standard
%end
{% if ansible_host is defined and ansible_host | ipaddr %}
network --bootproto=static --gateway={{
gateway | default((((ansible_host + '/255.255.255.0') | ansible.utils.ipaddr('network') | ansible.utils.ipaddr('int'))+1)|string|ansible.utils.ipaddr)
}} --ip={{ ansible_host }} --nameserver={{
nameserver | default((((ansible_host + '/255.255.255.0') | ansible.utils.ipaddr('network') | ansible.utils.ipaddr('int'))+1)|string|ansible.utils.ipaddr)
}} --netmask={{ netmask | default('255.255.255.0') }}
{%- else %}
network --bootproto=dhcp --hostname={{ inventory_hostname }}
{%- endif %} --device=enp0s3 --onboot=on --hostname={{ inventory_hostname }}
user --name={{ ansible_user | default(lookup('pipe', 'whoami')) }} --groups=wheel --password={{ ansible_password | password_hash }} --iscrypted
# Keyboard layouts
keyboard --xlayouts='de'
# System language
lang en_US.UTF-8
# Use network installation
url --url="https://yum.oracle.com/repo/OracleLinux/OL9/baseos/latest/x86_64"
%packages
@^server-product-environment
openscap
openscap-scanner
rsyslog
scap-security-guide
%end
%post --interpreter=/bin/bash
#---- Install our SSH key ----
mkdir -p -m0700 /home/{{ ansible_user | default(lookup('pipe', 'whoami')) }}/.ssh/
cat <<EOF >/home/{{ ansible_user | default(lookup('pipe', 'whoami')) }}/.ssh/authorized_keys
{% for ssh_key in ssh_keys %}
{{ ssh_key }}
{% endfor %}
EOF
### set permissions
chmod 0600 /home/{{ ansible_user | default(lookup('pipe', 'whoami')) }}/.ssh/authorized_keys
### change owner
chown -R {{ ansible_user | default(lookup('pipe', 'whoami')) }}:{{ ansible_user | default(lookup('pipe', 'whoami')) }} /home/{{ ansible_user | default(lookup('pipe', 'whoami')) }}/.ssh
### fix up selinux context
restorecon -R /home/{{ ansible_user | default(lookup('pipe', 'whoami')) }}/.ssh/
%end
# Run the Setup Agent on first boot
firstboot --enable
# Generated using Blivet version 3.4.0
ignoredisk --only-use=sda
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
part pv.116 --fstype="lvmpv" --ondisk=sda --grow --size=25600
part /boot --fstype="xfs" --ondisk=sda --size=1024
volgroup ol --pesize=4096 pv.116
logvol /var/log --fstype="xfs" --size=2048 --name=var_log --vgname=ol
logvol /var/log/audit --fstype="xfs" --size=1024 --name=var_log_audit --vgname=ol
logvol / --fstype="xfs" --grow --name=root --vgname=ol --size 20480
# System timezone
timezone Europe/Berlin --utc
# Disable root password
rootpw --lock
{% if reboot_after_installation %}
# Reboot after installation
reboot
{% endif %}