Skip to content

feat(ipe): add signed policy loading and Azure mode selection - #52

Merged
aadhar-agarwal merged 1 commit into
aclmainfrom
aadagarwal/acl-ipe-mode-toggle
Oct 9, 2026
Merged

aadhar-agarwal merged 1 commit into
aclmainfrom
aadagarwal/acl-ipe-mode-toggle

Conversation

@aadhar-agarwal

@aadhar-agarwal aadhar-agarwal commented Aug 14, 2026 •

Copy link
Copy Markdown

Summary

Adds opt-in, policy-only IPE audit for Azure UKI images, with signed policies bound to the UKI and signer-continuity checks during conversion. Azure IMDS activates only ipe=audit (enforce=0); loading failures are logged and leave IPE inactive without blocking boot.

/usr retains dm-verity without detached root-hash signatures. Kernel-trusted policies do not require Trusted Launch; test-signed candidates still need test trust. Enforcement is unsupported and production defaults remain disabled.

Shared landing timeline

The core implementation in PR 28754 lands as five reviewable PRs. Policy-only audit preparation and production activation follow as separate PRs.

  • Validate exact ACL and ACL Pipelines refs with production defaults disabled.
  • Merge Mantle PR 34 and validate Trusted Launch/VHD fallback.
  • Complete direct dev-image boot validation.
  • 1/5 Candidate asset contract - PR 29034.
  • 2/5 Offline IPE signing tools - PR 29040.
  • 3/5 Definition 5425 ESRP signing transaction - PR 29078.
  • 4/5 Exact gallery certificate publication - PR 29150.
  • 5/5 Final gallery trust and exact-image validation - PR 29151.
  • Defer /usr root-hash signing for policy-only audit - PR 29478.
  • microsoft/azure-container-linux#52 - This PR
  • Enable IPE audit testing in aclmain-based dev pipelines - PR 29563
  • Backport PR 52 into release/3.0
  • Enable IPE in production builds - PR 29392

@aadhar-agarwal aadhar-agarwal changed the title IPE functionality feat(ipe): add signed policy loading and Azure mode selection Aug 14, 2026
@aadhar-agarwal
aadhar-agarwal force-pushed the aadagarwal/acl-ipe-mode-toggle branch 2 times, most recently from fe37a53 to a449cd2 Compare August 14, 2026 18:32
@aadhar-agarwal
aadhar-agarwal force-pushed the aadagarwal/acl-ipe-mode-toggle branch 5 times, most recently from 6cbfb5e to 0db5ca5 Compare August 19, 2026 22:00
@mayankfz
mayankfz requested a balanced review from Copilot August 20, 2026 16:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds opt-in IPE support to Azure Secure Boot UKI images, including signed policies, dm-verity signatures, and IMDS-based permissive mode.

Changes:

  • Builds and loads signed IPE policies with signed /usr root hashes.
  • Adds Azure Trusted Launch certificate forwarding and runtime validation.
  • Adds supporting tests, CI parameters, documentation, and package fixes.

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
sdk_lib/sdk_entry.sh Forwards validated IPE settings.
sdk_lib/sdk_container_common.sh Adds version-file fallback.
run_sdk_container Streams external policies into containers.
run_azure_tests.sh Forwards Trusted Launch settings.
image_to_vm.sh Reuses IPE signing certificates.
ci-automation/vendor-testing/azure.sh Configures Trusted Launch and certificates.
build_library/rpm/uki_install.sh Signs and installs verity companions.
build_library/rpm/sign_uki_ephemeral.sh Supports shared signing certificates.
build_library/rpm/rpm_install.sh Installs signed policies and multi-RPM mappings.
build_library/rpm/package_catalog.yaml Adds explicit libgomp dependencies.
build_library/rpm/ipe_verity.sh Serializes validated root hashes.
build_library/rpm/ensure_ephemeral_cert.sh Generates shared ephemeral certificates.
build_library/rpm/dracut_install.sh Installs the IPE loader module.
build_library/rpm/additional_files/ipe/acl-ipe-boot-policy.pol Defines the IPE execution policy.
build_library/rpm/additional_files/dracut-acl-selinux-toggle/module-setup.sh Installs the shared profile helper.
build_library/rpm/additional_files/dracut-acl-selinux-toggle/acl-selinux-toggle.sh Uses shared IMDS parsing.
build_library/rpm/additional_files/dracut-acl-ipe-load/module-setup.sh Defines the IPE dracut module.
build_library/rpm/additional_files/dracut-acl-ipe-load/acl-ipe-load.sh Selects and activates IPE mode.
build_library/rpm/additional_files/dracut-acl-ipe-load/acl-ipe-load.service Orders early policy loading.
build_library/rpm/additional_files/acl-node-security-profile.sh Fetches and caches IMDS profiles.
build_library/build_image_util.sh Integrates policy installation.
acl/validate/validate_common.sh Forwards host-test timeouts.
acl/tests/test-run-sdk-container-ipe-policy.sh Tests policy streaming and reuse.
acl/tests/test-rpm-provider-selection.sh Tests multi-package mappings.
acl/tests/test-ipe-policy-input.sh Tests policy preparation and validation.
acl/tests/test-ipe-loader-runtime.sh Tests runtime mode selection.
acl/tests/test-azure-security-profile-test-common.sh Tests timeout contracts.
acl/tests/run-selinux-toggle-test.sh Reuses shared Azure helpers.
acl/tests/run-ipe-permissive-test.sh Validates permissive IPE behavior.
acl/tests/run-ipe-mode-toggle-test.sh Tests reboot-based IPE selection.
acl/tests/azure-security-profile-test-common.sh Shares Azure tag/reboot logic.
acl/docs/BUILD_RPM_IMAGE_README.md Documents policy build inputs.
acl/docs/architecture.md Documents IPE and verity architecture.
acl/build_rpm_image.sh Adds IPE configuration and validation.
.pipelines/github-pr-validation.yml Adds validation parameters.
Suppressed comments (1)

acl/docs/BUILD_RPM_IMAGE_README.md:173

  • The external-policy example also omits ACL_IPE_CAPABLE=true, so the supplied artifact is validated but never installed because rpm_install_ipe_policy returns immediately for the default disabled capability. Update this command to opt into IPE explicitly.
./acl/build_rpm_image.sh --rebuild \
  --ipe-policy-mode=external \
  --ipe-policy-path=/secure/input/acl.pol.p7b

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread acl/docs/BUILD_RPM_IMAGE_README.md Outdated
Comment thread acl/docs/BUILD_RPM_IMAGE_README.md Outdated
@aadhar-agarwal
aadhar-agarwal force-pushed the aadagarwal/acl-ipe-mode-toggle branch 3 times, most recently from 4758407 to 9b504fd Compare September 1, 2026 20:43
@aadhar-agarwal
aadhar-agarwal force-pushed the aadagarwal/acl-ipe-mode-toggle branch from ba4f50f to 5dd78a4 Compare September 8, 2026 19:25
Comment thread acl/tests/ipe/offline/test-ipe-policy-input.sh Outdated

@SeanDougherty SeanDougherty left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Four inline findings, each reproduced locally against this head.

Comment thread build_library/rpm/ipe_verity.sh Outdated
Comment thread image_to_vm.sh Outdated
Comment thread build_library/rpm/additional_files/acl-node-security-profile.sh Outdated
Comment thread acl/build_rpm_image.sh
Comment thread acl/build_rpm_image.sh

@SeanDougherty SeanDougherty left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Two Azure launch-contract blockers, both reproduced locally against this head.

Comment thread acl/build_rpm_image.sh Outdated
Comment thread run_azure_tests.sh Outdated
@bfjelds

Copy link
Copy Markdown
Member

two agent reviews revealed no issues. a run asking about refactor or shareable code had this:

Readability: yes, generally good. Clear step-numbered sections ( Step 0: ,  Step 1: ...), descriptive  test_*  function names, comments explaining why (e.g. mkfifo trick to simulate kernel policy activation), and consistent  fail / assert_*  helpers. A newcomer could follow the intent without deep IPE kernel knowledge. The main comprehension cost is that several tests reach into unrelated scripts' internals (see below), which requires jumping files to verify what's actually being tested.

Refactor opportunities:

1. Fragile  eval "$(sed -n '/^func() {/,/^}/p' file)"  extraction pattern, repeated in  test-azure-trusted-launch.sh ,  test-ipe-policy-input.sh  (×3), and  test-ipe-mode-toggle-logic.sh -adjacent tests. It breaks silently if the extracted function ever contains a nested here-doc or brace at column 0. Worth one shared helper, e.g.  source_functions <file> <func>...  in a test-common lib, so the fragile sed logic exists once.
2. Repetitive per-test boilerplate in  test-ipe-loader-runtime.sh : nearly every  test_*  repeats  prepare_case  →  make_credential  →  sha256sum | cut  →  printf 'acl.ipe.policy_sha256=%s\n' . A  write_hashed_cmdline <credential>  helper would collapse ~8 near-identical 4-line blocks into one call each.
3. Duplicated cmdline-parsing logic ( tr ' ' '\n' | sed -n 's/^usrhash=//p' | head -n1 , and the  verity_usr_options  →  root-hash-signature=  extraction) appears independently in both  run-ipe-mode-toggle-test.sh 's  assert_ipe_assets_present  and  run-ipe-permissive-test.sh . Same parsing, two implementations — a shared  cmdline_field <name>  function would remove the duplication and the risk of the two drifting apart.

Shareable code — already done well in one place, missing in another:

• Good:  acl-node-security-profile.sh 's  acl_security_profile_value  is explicitly reused by  run-ipe-mode-toggle-test.sh  ("so the host-side test can never disagree with production parsing" — a comment I'd hold up as the right pattern).
• Gap:  azure-security-profile-test-common.sh 's  imds_security_profile_state()  jq filter is a hand-copied variant of  acl_security_profile_parse()  in the production script, differing only by parameterizing the tag name. Since it's testing IMDS-response parsing, drift between the two is exactly the kind of bug this test suite exists to catch — extracting the jq program into one shared file (sourced by both) would close that gap the same way the  _value  reuse already does.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Security-sensitive UKI signing, initramfs activation, and external ESRP publication contracts require final human validation.

Review effort: Balanced
Findings: None

@SeanDougherty SeanDougherty left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Three current-head findings, each reproduced locally against the shipping functions.

Comment thread build_library/rpm/verify_ipe_signer_continuity.sh Outdated
Comment thread acl/validate/validate_common.sh Outdated
Comment thread acl/validate/validate_azure.sh
Copilot AI balanced review requested due to automatic review settings October 7, 2026 23:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Security-sensitive boot-chain, signing, initramfs, and Azure orchestration changes require final human validation.

0 open findings

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Copilot AI balanced review requested due to automatic review settings October 8, 2026 00:25
@aadhar-agarwal
aadhar-agarwal force-pushed the aadagarwal/acl-ipe-mode-toggle branch from 7c0e8d2 to 4736a51 Compare October 8, 2026 00:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The security-critical boot, signing, initramfs, and Azure publication changes require final human review and live end-to-end validation.

0 open findings

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Copilot AI balanced review requested due to automatic review settings October 8, 2026 03:12
@aadhar-agarwal
aadhar-agarwal force-pushed the aadagarwal/acl-ipe-mode-toggle branch from 4736a51 to 8ed94b2 Compare October 8, 2026 03:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

It changes boot-time trust, policy signing, UKI conversion, and Azure publication across a broad security-sensitive surface.

0 open findings

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

@SeanDougherty SeanDougherty left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Two design-contract questions from the current-head rereview.

Comment thread build_library/rpm/verify_ipe_signer_continuity.sh
Comment thread acl/validate/validate_azure.sh Outdated

@dallasd1 Dallas Delaney (dallasd1) left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No blocking comments found but I'd like to know if one of the PRs lights up ESRP signing for the policy

Comment thread build_library/rpm/rpm_install.sh
Copilot AI balanced review requested due to automatic review settings October 8, 2026 05:08
@aadhar-agarwal
aadhar-agarwal force-pushed the aadagarwal/acl-ipe-mode-toggle branch from 8ed94b2 to 48aec3d Compare October 8, 2026 05:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The Azure image-provenance guard can be bypassed using the supported -i image alias.

1 open finding

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread build_library/rpm/ipe_artifact.sh

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Azure CLI option abbreviations can bypass the ARM size and Trusted Launch override guard.

1 open finding
1 resolved since last review

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread acl/validate/test_validate_azure.sh Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

It changes the security-sensitive boot and signing chain across 39 files, and required CI validation is still in progress.

0 open findings

1 resolved since last review

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Bind the IPE policy to the boot signing identity and validate Azure image selection. Reject deterministic gallery collisions before VM cleanup, disallow policy-hash overrides in active UKI addons, reject short image arguments for IPE launches, and upload the exact preflighted VHD across latest symlink changes.

Signed-off-by: Aadhar Agarwal <aadagarwal@microsoft.com>

@liulanze Lanze Liu (liulanze) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ack. From the ACL-T side, here is how I read the contract this PR sets for an image whose UKI is rebuilt by Image Customizer. Please correct anything that is off.

  1. The rebuilt UKI keeps EFI/Linux/<uki>.efi.extra.d/acl-ipe-policy.p7b.cred and keeps acl.ipe.policy_sha256 in the main UKI command line, never in an addon.
  2. The credential and the UKI are signed by the same certificate, and that certificate is the one enrolled in the UEFI db. ACL-T signs its UKI with its own per-build certificate, so it re-signs the credential with that certificate and rewrites the token to the new digest before the UKI signature, using the shared-certificate form of sign_uki_ephemeral.sh.
  3. For the production path, the ACL-T artifact carries the ipe-signing-mode marker and the raw policy from the stock drop, and the publish pipeline runs the same ESRP finalize on it as on stock ACL: new CMS, fixed-width token rewrite in the main UKI, UKI re-sign.
  4. The runtime side needs nothing ACL-T specific: the loader keys off flatcar.oem.id=azure and the IMDS tag, and fails open.

@aadhar-agarwal

Copy link
Copy Markdown
Author

Ack. From the ACL-T side, here is how I read the contract this PR sets for an image whose UKI is rebuilt by Image Customizer. Please correct anything that is off.

  1. The rebuilt UKI keeps EFI/Linux/<uki>.efi.extra.d/acl-ipe-policy.p7b.cred and keeps acl.ipe.policy_sha256 in the main UKI command line, never in an addon.
  2. The credential and the UKI are signed by the same certificate, and that certificate is the one enrolled in the UEFI db. ACL-T signs its UKI with its own per-build certificate, so it re-signs the credential with that certificate and rewrites the token to the new digest before the UKI signature, using the shared-certificate form of sign_uki_ephemeral.sh.
  3. For the production path, the ACL-T artifact carries the ipe-signing-mode marker and the raw policy from the stock drop, and the publish pipeline runs the same ESRP finalize on it as on stock ACL: new CMS, fixed-width token rewrite in the main UKI, UKI re-sign.
  4. The runtime side needs nothing ACL-T specific: the loader keys off flatcar.oem.id=azure and the IMDS tag, and fails open.

Yup that matches the intended contract.

ACL-T currently signs the rebuilt UKI with a new cert but does not re-sign the IPE credential. It needs to sign both with the same key and update the policy hash in the UKI before signing the UKI.

@jiria

Copy link
Copy Markdown
Member

In the standalone path where no shared certificate directory is supplied, sign_uki_ephemeral.sh generates its own certificate with the same openssl req options used by ensure_ephemeral_cert.sh (RSA size, one-day lifetime, subject, and code-signing extensions). Could this path use that helper within its existing scratch directory and copy out only the public PEM? The scratch-directory cleanup would still remove the private key, while future changes to the certificate recipe would stay in one place. The two paths agree today, so this is a nonblocking maintainability suggestion.

This branch was successfully deployed

1 active deployment
development — 8da1cc91 Deployed Oct 8, 2026 by aadhar-agarwal via Check if we need to update the SDK #107
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.

8 participants