Skip to content

chuckmilam/create-ks-iso

Repository files navigation

Create kickstart (ISO)

Basic CI Tests using Docker

Dynamically creates a kickstart file with optional randomly-generated bootstrap user credentials, useful for STIG compliance testing in an automation pipeline. Includes options for creating custom ISO images to enable non-interactive FIPS-compliant installations of a RHEL-based Linux distributions.

Overview

create-ks-iso.sh is intended to be a simple, lightweight, dynamic solution to generate a STIG-compliant kickstart file and installer boot ISO image. Optionally, the user can create an OEMDRV ISO for delivering the kickstart file to the system installer; useful in environments where PXE boot or similar network delivery methods may not be available. Bootstrap user credentials may be either randomly-generated or specifically declared as required to fit operational needs. The kickstart file can be tailored at the point of generation. Default settings are easily changed either by editing the included CONFIG_FILE template or by setting environment variables at runtime, potentially allowing for use in automation pipelines.

The Challenges of RHEL STIG Compliance

There are two aspects of RHEL STIG compliance efforts that realistically should be addressed at install time:

  1. Setting Federal Information Processing Standard (FIPS) 140-2 mode
  2. Configuring whole-disk encryption

This project attempts to address both challenges.

FIPS Mode

While FIPS mode can be enabled after the OS install, it is not the recommended practice and can leave the system in an inconsistent state on first boot when testing for FIPS mode.

Per the RHEL 9 Security Hardening Guide (Red Hat login may be required for access):

Red Hat recommends installing RHEL with FIPS mode enabled, as opposed to enabling FIPS mode later. Enabling FIPS mode during the installation ensures that the system generates all keys with FIPS-approved algorithms and continuous monitoring tests in place.

Anecdotally, inspectors/auditors may ask for proof that the system was installed with FIPS enabled rather than switched on after an install. Therefore, where FIPS mode is required, it is recommended to create the modified boot ISO (set CREATEBOOTISO="true") option here and then use it to install the OS.

Whole-Disk Encryption

The RHEL 8 STIG introduced the de facto requirement that all system partitions are encrypted, unless "...there is a documented and approved reason for not having data-at-rest encryption...."

The RHEL 9 STIG took this a step further, making data-at-rest encryption a CAT I / HIGH Severity STIG finding. The exception where "...there is a documented and approved reason for not having data-at-rest encryption, this requirement is Not Applicable." is still present.

Again, anecdotally, it is easier to comply with the STIG check than try to debate an inspector or auditor over just what "documented and approved" means.

Without a method to provide the encryption key/passphrase to unlock system partitions, the system will hang at boot waiting for the passphrase to be typed in at the console. If each individual partition is encrypted, then a passphrase must be entered for every partition. This project provides a method of "baking in" the keyfile to auto-decrypt the system partitions without the need to set up a clevis/tang environment. By encrypting the LVM physical volume instead of the logical volumes, resize operations can occur while leaving disk encryption in place.

Requirements

  • A Linux system. RHEL/CentOS, Ubuntu, and WSL have all been tested successfully, but primary focus has been on Red Hat-derived distributions. System should have these packages installed:
    • bash v4+
    • genisoimage
    • git
    • grub2-tools-minimal
    • isomd5sum
    • OpenSSH
    • OpenSSL
    • syslinux
    • pykickstart (for running ksvalidator checks)
  • When creating a custom boot ISO:
    • RHEL-based full install ISO, readable by the user running the script.
    • root/sudo permissions in order to mount the ISO image.
    • Sufficient disk space for ISO creation. Enough is needed for the source OEM install ISO, temporary space for the extracted OEM install ISO, and then the final custom boot ISO. Consider that RHEL 8 and 9 boot ISOs are between 9-12G in size, so plan on at least 3x that size.

There is also a container-based option that has been tested with Docker/Podman. This method frees up the need to chase dependencies on the host system, and it even works on Windows hosts. It's good for chicken/egg problems in Microsoft-first environments or when moving to a new major Linux distribution release version.

Installation

No installation is required, and this can be run directly from a user home directory on Linux systems. To use create-ks-iso, simply clone the GitHub repository:

git clone https://github.com/chuckmilam/create-ks-iso

Once the repository is cloned, change into the project directory and run the script with default settings:

cd create-ks-iso
./create-ks-iso.sh

Assuming all dependency checks pass, the default settings will generate a kickstart file (ks.cfg) in the current working directory, as well as some SSH keys in the "creds" directory.

No ISOs are created unless the default settings are changed.

Usage

create-ks-iso attempts to be flexible to fit various use cases. Some examples:

Customize Script Settings

Variables can be set by editing the CONFIG_FILE directly, or by using environment variables.

Generate a kickstart file

To generate a kickstart file, simply run the script:

./create-ks-iso.sh

This command will generate a kickstart file in the current directory. Note FIPS mode is not enabled in the generated kickstart file. This may not meet STIG compliance requirements.

Generate an OEMDRV volume ISO

This ISO volume allows the kickstart file to be detected and run by the system installer with no manual intervention required. In the most common cases, the system install ISO is attached to the machine in the first CD/DVD drive.

CREATEOEMDRVISO="true" ./create-ks-iso.sh

Attach this OEMDRV ISO to the machine to be installed in a second CD/DVD drive and boot from the first CD/DVD drive. It should load and run the kickstart install automatically.

Generate a Custom RHEL Boot ISO with FIPS mode enabled

For this option, a RHEL-based full install ISO, readable by the user running the script, must be available. Default location for this install ISO is $SRCDIR/isosrc, but can be controlled by the ISOSRCDIR variable.

Note the use of sudo -E to ensure the environment variables are passed into the sudo session.

CREATEBOOTISO="true" ENABLEFIPS="true" sudo -E ./create-ks-iso.sh

Generate a Custom RHEL Boot ISO with FIPS mode enabled with ks.cfg built-in

This option bakes the kickstart file directly into the boot ISO, useful for systems limited to only a single bootable drive for the ISO image.

Again, a RHEL-based install ISO is required as above, and note the use of sudo -E to ensure the environment variables are passed into the sudo session.

CREATEBOOTISO="true" KSINBOOTISO="true" ENABLEFIPS="true" sudo -E ./create-ks-iso.sh

Sanitize the working directories

Run the sanitize script to remove any generated user credentials, kickstart, and ISO files.

./sanitize-create-ks-iso.sh

Be sure to specify the same configuration/environment variables if any were used to change default path names in the initial run of create-ks-iso.sh.

Docker or Podman Usage

This has been tested on Linux and Windows docker hosts, and is still under development.

To get started, from the git cloned directory (example below uses docker, but podman should be a drop-in replacement for this use case):

  1. Create a local ISO source directory where your OEM install ISO will reside. Default name is: "isosrc."

  2. Create a local directory for the generated files. Default name is: "result."

  3. Build the image:

    docker build -t chuckmilam/create-ks-iso:latest .
    
  4. Then run the container. You can pass environment variables similar to running on a native Linux host, but we do pass the USER variable in to the container so it won't be NULL. The example below is shown using a Windows Docker host. Note the required use of the --privileged switch when building the boot iso, to allow mount of the ISO file system in the build script.

    docker run --privileged --env USER=${Env:UserName} --env WRITEPASSWDS="true" --env CREATEBOOTISO="true" --env ENABLEFIPS="true" --env KSINBOOTISO="true" --env password="Password1234" --env CREATEOEMDRVISO="true" --mount type=bind,source=${PWD}\result,target=/create-ks-iso/result --mount type=bind,source=${PWD}\isosrc,target=/create-ks-iso/isosrc chuckmilam/create-ks-iso:latest
    

    Here is the Linux version of the above. The only change is the Linux vs. Windows directory path syntax:

    docker run --privileged --env USER=${USER} --env WRITEPASSWDS="true" --env CREATEBOOTISO="true" --env ENABLEFIPS="true" --env KSINBOOTISO="true" --env password="Password1234" --env CREATEOEMDRVISO="true" --mount type=bind,source=./result,target=/create-ks-iso/result --mount type=bind,source=./isosrc,target=/create-ks-iso/isosrc chuckmilam/create-ks-iso:latest
    

The fedora:latest image is used instead of Red Hat UBI or Alpine because several required packages are not readily available in the traditional light images.

Roadmap

Things to implement/improve:

  • Move ks.cfg into its own subdir under result
  • Modify /etc/issue message to include username
  • Replace soon-to-be-deprecated python crypt module in encrypt_random_passwd function.
  • Make configurable as variables in ks.cfg:
    • Disk partition sizes
    • NTP configuration
    • Network settings
  • DOCKERFILE for portability and network functionality
    • Find a RHEL base image that has the needed packages available
    • Docker configuration for network kickstart delivery
  • Complete CONFIG_FILE template with available variables
  • STIG oscap/anaconda plugin logic based on OS distribution and version
  • Checks for required packages for ISO creation
  • ksvalidator checks
  • Change ntpserver kickstart statement per major OS version (8.x vs 9.x)
  • Utilize "light" installer ISO for network-based installs
  • Option to create FIPS-enabled boot ISO without baked-in kickstart file
  • Option to specify a different kickstart location (HTTP/S, NFS, etc.)
  • Option to write generated SSH keys and passwords into ISO
  • Warning if setting FIPS mode without creating boot ISO
  • Option to turn off STIG-specific settings for non-STIG use cases
  • Option to write randomly-generated creds into a vault (post-hook?)

History

The initial script harkens back to when I first started using kickstart. Faced with the (re)deployment of 200+ Linux workstations that had to be disk-wiped and redeployed frequently, I knew I needed to automate. PXE booting and kickstart were sanity-savers. Later, adding STIG compliance requirements brought additional challenges. Rapid prototyping and testing with virtualization helped streamline it further. Now I'm looking to use it for automated pipeline testing in places where containers don't quite make sense.

Acknowledgments

This project references and acknowledges the following resources:

About

Create kickstart files and STIG-compliant bootable ISO files with randomized credentials for use in CI/CD testing.

Topics

Resources

Stars

Watchers

Forks