engineering: Port osmodifier from Go binary to native Rust crate#638
Open
bfjelds wants to merge 60 commits into
Open
engineering: Port osmodifier from Go binary to native Rust crate#638bfjelds wants to merge 60 commits into
bfjelds wants to merge 60 commits into
Conversation
Member
Author
|
/azp run [GITHUB]-trident-pr-e2e |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Member
Author
|
/azp run [GITHUB]-trident-pr-e2e |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Member
Author
|
/azp run [GITHUB]-trident-pr-e2e |
|
Azure Pipelines successfully started running 1 pipeline(s). |
9fff08e to
2fb0625
Compare
Member
Author
|
/azp run [GITHUB]-trident-pr |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Member
Author
|
/azp run [GITHUB]-trident-pr-e2e |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Member
Author
|
/azp run [GITHUB]-trident-pr-e2e |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Member
Author
|
/azp run [GITHUB]-trident-pr-e2e |
|
Azure Pipelines successfully started running 1 pipeline(s). |
becb22b to
ccabced
Compare
Member
Author
|
/azp run [GITHUB]-trident-pr-e2e |
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
Member
Author
|
/azp run [GITHUB]-trident-pr-e2e |
|
Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command. |
Replace the external Go osmodifier binary from azure-linux-image-tools with a native Rust library crate (crates/osmodifier). Trident now calls osmodifier functions directly instead of serializing config to YAML, writing a temp file, and exec'ing the Go binary. The new crate implements: - User management (useradd, password hashing, SSH keys, groups) - Hostname configuration (/etc/hostname) - Service management (systemctl enable/disable) - Kernel module configuration (modules-load.d, modprobe.d) - SELinux configuration (/etc/selinux/config and kernel cmdline) - /etc/default/grub parsing and writing - grub.cfg parsing for update-default-grub flow - grub2-mkconfig execution Public API: - modify_os() - replaces osmodifier --config-file for OS modifications - update_default_grub() - replaces osmodifier --update-grub - modify_boot() - replaces osmodifier --config-file for boot config This eliminates: - External Go binary build dependency (azure-linux-image-tools clone) - Binary bind-mounting into newroot - YAML serialization round-trip overhead - OS_MODIFIER_BINARY_PATH and OS_MODIFIER_NEWROOT_PATH constants - Makefile, Dockerfile, RPM spec, and pipeline osmodifier references Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ed import Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…l tests Remove all download-osmodifier.yml template invocations, make artifacts/osmodifier targets, and functional test binary upload steps. The osmodifier is now compiled into the trident binary as a library crate. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Change days_since_unix_epoch from returning a bare i64 (with unwrap_or_default silently producing 0 on pre-1970 clocks) to returning Result<i64>. A pre-epoch system clock now fails the operation explicitly instead of silently setting account expiry to day 0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add doc comment on find_non_recovery_linux_lines explaining the known limitation where submenu blocks are not tracked. This matches Go's FindNonRecoveryLinuxLine behavior and is acceptable because AZL images built by trident have exactly one kernel installed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Storage-Rules.md: rename first column header from 'Mount Path' to 'Partition Type' — column lists partition types, not mount paths. - trident_api SelinuxMode: add 'security=selinux' to Permissive and Enforcing doc comments to match actual kernel args set by osmodifier. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Correct the doc comment to reflect that both the chroot'd boot path and the MOS configuration path use OsModifierContext::default() (root '/') in production. The non-'/' option is for unit tests only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Route the error through parse_err like the other error paths in the shadow file map closure, since the closure returns String not Result. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add blank lines before paragraphs that follow numbered/bulleted lists in doc comments to prevent clippy from treating them as list items. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The schema descriptions for permissive and enforcing modes omitted the security=selinux kernel arg that the code actually appends. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The valid_mount_paths table header said 'Mount Path' but the rows contain partition type names (esp, root, etc.), not mount paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Run make build-api-docs to regenerate: - host-config-schema.json: enforcing description now includes security=selinux LSM explanation from Rust doc comment - SelinuxMode.md: permissive and enforcing descriptions updated with security=selinux kernel arg Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The osmodifier crate uses serde but not serde_yaml directly. Config deserialization happens in the caller (trident crate). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use child.stdin.take() to explicitly close the pipe after writing, ensuring the child process receives EOF. While wait_with_output() does this internally, explicit take() is idiomatic and clearer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Member
Author
|
/azp run [GITHUB]-trident-pr-e2e |
|
Azure Pipelines successfully started running 1 pipeline(s). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Port the Go osmodifier from azure-linux-image-tools to a native Rust library crate (
crates/osmodifier). Trident now calls osmodifier functions directly instead of serializing config to YAML, writing a temp file, and exec'ing the Go binary.See
crates/osmodifier/README.mdfor full documentation including file mapping, function mapping, intentional divergences, and sync guide.Architecture
Three public entry points replace the single Go binary:
modify_os(&ctx, &config)modify_boot(&ctx, &boot_config)update_default_grub(&ctx)osmodifier --update-grub: sync grub.cfg values back to /etc/default/grubKey design decisions:
Result./.boot/mod.rsbeforemodify_boot()is called.modify_os()vsmodify_boot()for pipeline stage separation.What changed
New crate:
crates/osmodifierRust library implementing all Go osmodifier functionality:
useradd, password hashing (chpasswd -evia stdin, not cmdline), SSH authorized_keys (preserving existing keys for existing users), groups, startup command, password expiry (shadow field 7 with absolute date matching Go'sChage())/etc/hostnamewrite (no trailing newline, matching Go)systemctl enable/disablewith Go-faithful error handling (distinguishes "disabled" from "not found")modules-load.d,modprobe.dwith option merging, bare-flag preservation, duplicate-line consolidation/etc/selinux/configupdate, kernel cmdline args (security=selinux,selinux=,enforcing=), first-match-only replacement/etc/default/grubparsing/writing, targetsGRUB_CMDLINE_LINUX_DEFAULT, append-only cmdline argsgrub.cfgboot-arg extraction with string-based parsing (no regex), case-sensitive recovery detection scoped to quoted title tokenSecurity
chpasswd -e(not process cmdline):,\n, and\rto prevent/etc/passwdcorruption:and newlines before writing to/etc/shadow/etc/shadowand/etc/passwdwith uid/gid ownership preservation viafchownPasswordType::Lockedwrites!marker for existing usersIntegration
osutils::Dependencyenum (systemctl, grub2-mkconfig, id, useradd, usermod, chown, openssl, chpasswd)osutils::osmodifierre-export shim to break cyclic dependencyBuild and packaging
download-osmodifier.ymltemplate, Makefile osmodifier targets, Dockerfile osmodifier stages, functional test binary upload stepsRequires: openssl, shadow-utils; addedSuggests: grub2-toolsOS_MODIFIER_BINARY_PATHandOS_MODIFIER_NEWROOT_PATHconstantsTests
Documentation
crates/osmodifier/README.md: Go-to-Rust file mapping, function-by-function mapping (17 functions), intentional divergences, not-ported table with rationale, sync guide with git commands and change-type-to-file mappingFidelity
Two rounds of systematic Go-vs-Rust comparison, plus a 9-agent adversarial deep review (3 roles × 3 model families). All behavioral divergences found were fixed:
systemd.IsServiceEnabled=, merge duplicateoptions <module>linessecurity=selinuxkernel arg for Enforcing/Permissive, Enforcing matches Go's EMU path (noenforcing=1)GRUB_CMDLINE_LINUX_DEFAULT(notGRUB_CMDLINE_LINUX), append-only (no key dedup)Chage(), preserve existingauthorized_keysfor existing users, error on unparseable shadowlastChangeSource mapping
Ported from
azure-linux-image-tools(toolkit/tools/):lib.rsosmodifierlib/osmodifier.go,modifierutils.gof4de1a0config.rsosmodifierapi/os.go,overlay.go,verity.go,identifiedpartition.go8bd4ef3users.rsimagecustomizerlib/customizeusers.go8bd4ef3hostname.rsimagecustomizerlib/customizehostname.go8bd4ef3modules.rsimagecustomizerlib/kernelmoduleutils.go8bd4ef3services.rsimagecustomizerlib/customizeservices.godc90945selinux.rsmodifierutils.go(SELinux functions)f4de1a0default_grub.rsmodifydefaultgrub.gof4de1a0grub_cfg.rsmodifydefaultgrub.go,modifierutils.gof4de1a0