Skip to content

feat(azure): Add Azure Ignition fragment generation#1264

Open
peytonr18 wants to merge 4 commits intocoreos:mainfrom
peytonr18:probertson-generate-ignition-config
Open

feat(azure): Add Azure Ignition fragment generation#1264
peytonr18 wants to merge 4 commits intocoreos:mainfrom
peytonr18:probertson-generate-ignition-config

Conversation

@peytonr18
Copy link

@peytonr18 peytonr18 commented Mar 19, 2026

Summary

This PR adds Azure-specific Ignition fragment generation in Afterburn so Ignition can consume platform-provided user data during merge and create/configure the target user with SSH authorized keys.

Changes

  • Added a new render-ignition CLI subcommand that accepts --provider/--cmdline, --render-ignition-dir, and per-feature flags.`
  • Added Azure fragment generation logic:
    • generate_hostname_fragment(): fetches hostname via MetadataProvider::hostname(), writes hostname.ign with a data:,<hostname> URI.
    • generate_user_fragment(): reuses existing IMDS username/SSH key fetch and OVF validation for Azure, writes user.ign.
  • Added a new initrd systemd unit to run fragment generation in the Ignition window.
  • Wired the new unit into dracut module installation and first-boot target links.
  • Hardened IMDS SSH key parsing by sharing strict OpenSSH key validation logic between existing Azure SSH key retrieval and fragment generation paths.

OVF / IMDS Source Rules

  • Username and SSH keys come from IMDS.
  • The only field read from ovf-env.xml is adminPassword.
  • Non-empty OVF adminPassword is treated as unsupported and rejected.

CLI Design

The new render-ignition subcommand mirrors the existing multi pattern:

afterburn render-ignition --cmdline --render-ignition-dir <path> --hostname --platform-user
afterburn render-ignition --cmdline --render-ignition-dir <path> --platform-extensions
  • --render-ignition-dir <path> — directory to write .ign fragments into
  • --hostname — generate hostname.ign (Ignition storage.files entry for /etc/hostname)
  • --platform-user — generate user.ign (Ignition passwd.users entry with username + SSH keys)
  • --platform-extensions — enable all features (implies --hostname --platform-user)
    Each feature writes its own standalone fragment file. Unsupported features for a given provider warn and skip, matching existing afterburn behavior.

Existing functionality is untouched

The multi subcommand's --hostname=<path> direct-file-write path is unchanged. The afterburn-hostname.service (including its azure/azurestack conditions) is not modified.

The CLI design is up for discussion — we would love feedback on the flag names, subcommand structure, and overall approach.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for generating Azure-specific Ignition fragments. The implementation is well-structured, adding a new CLI command, a systemd service for execution, and the core logic for fetching data from IMDS and OVF. The refactoring to share SSH key parsing logic is a good improvement.

I've found one critical issue regarding the systemd service activation which would cause the feature to not work as intended, and one medium-severity suggestion to improve code efficiency and readability. Please see the detailed comments.

mkdir -p "$initdir/$systemdsystemunitdir/ignition-complete.target.requires"
ln -s "../afterburn-hostname.service" "$initdir/$systemdsystemunitdir/ignition-complete.target.requires/afterburn-hostname.service"
ln -s "../afterburn-network-kargs.service" "$initdir/$systemdsystemunitdir/ignition-complete.target.requires/afterburn-network-kargs.service"
ln -s "../afterburn-ignition-fragment.service" "$initdir/$systemdsystemunitdir/ignition-complete.target.requires/afterburn-ignition-fragment.service"

Choose a reason for hiding this comment

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

high

The afterburn-ignition-fragment.service is being linked into ignition-complete.target.requires. This will cause it to run after all main Ignition stages are complete, which is too late for the generated fragment to be used by Ignition.

According to its own unit file, this service must run before ignition-kargs.service. To ensure correct ordering and activation, it should be made a requirement of ignition-kargs.service instead of ignition-complete.target.

Suggested change
ln -s "../afterburn-ignition-fragment.service" "$initdir/$systemdsystemunitdir/ignition-complete.target.requires/afterburn-ignition-fragment.service"
mkdir -p "$initdir/$systemdsystemunitdir/ignition-kargs.service.requires"
ln -s "../afterburn-ignition-fragment.service" "$initdir/$systemdsystemunitdir/ignition-kargs.service.requires/afterburn-ignition-fragment.service"

Comment on lines +119 to +124
let key_data = item
.key_data
.replace("\r\n", "")
.replace('\n', "")
.trim()
.to_string();

Choose a reason for hiding this comment

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

medium

The current string manipulation for cleaning key_data involves a chain of operations that results in an unnecessary String allocation because .to_string() is called on a temporary &str. This can be made more efficient and readable by separating the steps.

Suggested change
let key_data = item
.key_data
.replace("\r\n", "")
.replace('\n', "")
.trim()
.to_string();
let key_data_cleaned = item.key_data.replace("\r\n", "").replace('\n', "");
let key_data = key_data_cleaned.trim();

@peytonr18 peytonr18 force-pushed the probertson-generate-ignition-config branch from 6af9c2e to 50a81df Compare March 19, 2026 19:04
@prestist prestist self-requested a review March 20, 2026 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant