Skip to content

Add keylimectl commands and interoperability tests - #1125

Draft
ansasaki wants to merge 20 commits into
RedHat-SP-Security:mainfrom
ansasaki:keylimectl-commands
Draft

ansasaki wants to merge 20 commits into
RedHat-SP-Security:mainfrom
ansasaki:keylimectl-commands

Conversation

@ansasaki

@ansasaki ansasaki commented Aug 20, 2026 •

Copy link
Copy Markdown
Contributor

Add the following tests:

  • functional/keylimectl-commands: Test individual keylimectl commands
  • compatibility/policy-tool-interop: Test that policies created and signed by keylime-policy works with keylimectl and vice-versa
  • compatibility/tenant-keylimectl-interop: Test that agents enrolled with the keylime_tenant can be managed by keylimectl and vice-versa

Summary by Sourcery

Expand integration coverage for keylimectl commands and interoperability while tightening test configuration handling and upstream feature setup.

New Features:

  • Add functional coverage for keylimectl help, policy generation and management, signing, validation, conversion, measured boot, diagnostics, configuration, and agent lifecycle commands.

Bug Fixes:

  • Prevent configuration updates from modifying unrelated files when a section-specific configuration file exists.

Enhancements:

  • Add interoperability coverage between keylimectl, keylime-policy, and keylime_tenant for policies, signatures, and agent management across pull and push attestation modes.

Build:

  • Enable the upstream Rust Keylime setup to compile the keylimectl RPM-repository, local-TPM, and TPM quote-validation features explicitly.

Tests:

  • Add functional keylimectl command tests and compatibility tests for policy-tool and tenant/keylimectl interoperability.

ansasaki and others added 4 commits August 20, 2026 17:33
Add comprehensive BeakerLib test for the keylimectl CLI tool covering:
- Help flags for all subcommands
- Runtime policy generation (IMA log, allowlist, excludelist, rootfs,
  hash algorithms, ramdisk, local and remote RPM repos, keyrings,
  verification keys in PEM and DER encoding for keys and certificates)
- Policy signing with ECDSA and X509 DSSE backends (including RSA keys)
- Measured boot policy generation
- Runtime policy CRUD on verifier (push/show/list/update/delete)
- Measured boot policy CRUD on verifier
- Agent lifecycle (add/status/list/update/reactivate/remove)
- Agent failure and recovery scenarios

The tests supports push and pull model test variants using the
AGENT_SERVICE environment variable pattern, consistent with other tests
in the repository.

Also update install_upstream_rust_keylime setup task to explicitly
enable non-default features (keylimectl/rpm-repo, keylimectl/tpm-local,
keylimectl/tpm-quote-validation) instead of --all-features, avoiding
deprecated features (with-zmq, legacy-python-actions).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Test that agents enrolled with keylime_tenant (v2 API) can be managed
with keylimectl (v3 API) and vice versa. Both tools map to the same
verifiermain DB table so no re-enrollment is needed when migrating.

The test covers two enrollment scenarios in each attestation mode:
- Enroll with keylime_tenant, remove with keylimectl
- Enroll with keylimectl, delete with keylime_tenant

Run with AGENT_SERVICE=Agent (default) for pull mode or
AGENT_SERVICE=PushAgent for push mode.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Test that runtime policies created and signed by keylime-policy are
usable with keylimectl and vice versa. Both tools produce DSSE-format
policies from the same underlying library, so cross-tool usage should
be transparent to the verifier.

Covers:
- Both tools produce structurally valid runtime policies
- keylime-policy policy accepted by keylimectl agent add
- keylimectl policy accepted by keylime_tenant add
- Signature produced by keylime-policy verified by keylimectl
- keylimectl policy push with keylime-policy-created policy

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
@sourcery-ai

sourcery-ai Bot commented Aug 20, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Adds new beakerlib test suites for keylimectl functionality and interoperability with keylime-policy and keylime_tenant, and updates the Rust keylime build to enable required keylimectl features.

File-Level Changes

Change Details Files
Introduce compatibility tests validating policy-format and signature interoperability between keylime-policy and keylimectl, and enrollment interoperability between keylime_tenant and keylimectl (including push and pull attestation modes).
  • Set up keylime services (registrar, verifier, agent/PushAgent) with TPM emulator and IMA support as needed using existing lime* helpers.
  • Generate runtime policies with keylime-policy and keylimectl, verify structural JSON validity and compare top-level keys.
  • Exercise cross-tool enrollment flows: use keylime-policy-generated runtime policies with keylimectl agent add, and keylimectl-generated policies with keylime_tenant add, including scripted expect-based keystore password entry.
  • Test cross-tool DSSE signature verification: sign policies with keylime-policy and keylimectl using ECDSA keys and verify signatures with keylimectl.
  • Test policy server operations where keylimectl pushes, lists, shows, and deletes policies created by keylime-policy.
  • Add tenant-keylimectl interop tests that enroll an agent with keylime_tenant and manage it with keylimectl, and vice versa, covering both Agent (pull) and PushAgent modes and verifying attestation status transitions and cleanup flows.
compatibility/policy-tool-interop/main.fmf
compatibility/policy-tool-interop/test.sh
compatibility/tenant-keylimectl-interop/main.fmf
compatibility/tenant-keylimectl-interop/test.sh
Add a comprehensive functional test suite for keylimectl commands covering help output, local policy generation, signing backends, measured-boot policies, verifier-side CRUD, agent lifecycle management, and failure/recovery flows.
  • Create a beakerlib-based functional test harness that prepares shared test data (IMA logs, base policies, allow/exclude lists, rootfs, measured-boot logs, RPM repos) from the existing keylime-policy-commands assets.
  • Validate --help/-h behavior for keylimectl and all subcommands (agent, policy, measured-boot, info, configure) to catch CLI regressions.
  • Exercise keylimectl policy generate runtime with various inputs and options: IMA measurement list, IMA log, base policy, allowlist/excludelist, rootfs hashing with multiple algorithms, ramdisk-dir, ima-buf, keyrings and ignored-keyrings, and addition of IMA signature verification keys from multiple key/cert formats.
  • Test runtime policy generation from local and remote RPM repositories using a temporary python HTTP server, verifying expected digests for test RPM content.
  • Test policy signing via ECDSA DSSE backend, including key auto-generation, custom key paths, failure cases for bad/nonexistent keys, and signature verification via limeVerifyRuntimePolicySignature.
  • Test policy signing via X509 DSSE backend, covering auto-generated certificates, RSA/EC key + cert combos, missing certificate error cases, and verification using both private keys and certificates.
  • On supported architectures, generate measured-boot policies from event logs, checking secureboot flags and kernel hashes, and validating that --without-secureboot is honored even when secure boot is present.
  • Configure keylimectl TLS via /etc/keylime/keylimectl.conf to use the verifier’s auto-generated certificates, then exercise verifier-side runtime policy CRUD (push/show/list/update/delete) and measured-boot CRUD.
  • Run full agent lifecycle tests: agent add/update/reactivate/remove, status and list against verifier and registrar, handling of push vs pull modes and expected attestation_status values.
  • Simulate agent failure with a bad script, observe FAIL/Invalid Quote, extend excludelist, regenerate runtime policy and confirm recovery after agent update.
  • Ensure bad runtime policies cause agent add to fail, and perform cleanup of services, temp dirs, and restored configs at the end of the test.
functional/keylimectl-commands/main.fmf
functional/keylimectl-commands/test.sh
Update Rust keylime upstream installation test to build with explicit keylimectl features required by the new tests while preserving existing testing feature behavior.
  • Define CARGO_FLAGS to enable non-default keylimectl features: rpm-repo, tpm-local, and tpm-quote-validation, explicitly excluding deprecated features.
  • When TPM_BINARY_MEASUREMENTS is set, append keylime_agent/testing to CARGO_FLAGS instead of replacing the flag set, ensuring measured-boot testing remains available alongside keylimectl features.
setup/install_upstream_rust_keylime/test.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@ansasaki
ansasaki marked this pull request as draft August 20, 2026 15:41
@ansasaki
ansasaki requested a review from kkaarreell August 20, 2026 15:41
@@ -0,0 +1,122 @@
#!/bin/bash
# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
. /usr/share/beakerlib/beakerlib.sh || exit 1
rlRun "jq . policy-from-kp.json > /dev/null" 0 "keylime-policy output is valid JSON"
rlRun "jq . policy-from-kctl.json > /dev/null" 0 "keylimectl output is valid JSON"
rlRun -s "jq -r 'keys | sort | .[]' policy-from-kp.json"
KP_KEYS="$rlRun_LOG"
@@ -0,0 +1,103 @@
#!/bin/bash
# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
. /usr/share/beakerlib/beakerlib.sh || exit 1
rlRun "limeWaitForAgentStatus ${AGENT_ID} 'Get Quote'"
fi
rlRun -s "keylimectl agent list"
rlAssertGrep "${AGENT_ID}" "$rlRun_LOG"
@@ -0,0 +1,615 @@
#!/bin/bash
# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
. /usr/share/beakerlib/beakerlib.sh || exit 1

rlPhaseStartTest "measured-boot list"
rlRun -s "keylimectl measured-boot list"
rlAssertGrep "testmb1" $rlRun_LOG

rlPhaseStartTest "agent list"
rlRun -s "keylimectl agent list"
rlAssertGrep "${AGENT_ID}" $rlRun_LOG

rlPhaseStartTest "agent list --registrar"
rlRun -s "keylimectl agent list --registrar"
rlAssertGrep "${AGENT_ID}" $rlRun_LOG
rlRun "limeWaitForAgentStatus $AGENT_ID '(Failed|Invalid Quote)'"
rlRun "rlWaitForCmd 'tail -n 30 \$(limeVerifierLogfile) | grep -q \"Agent $AGENT_ID failed\"' -m 10 -d 1 -t 10"
fi
limeExtendNextExcludelist $TESTDIR
limeSubmitCommonLogs
limeClearData
limeRestoreConfig
limeExtendNextExcludelist $TESTDIR

@sourcery-ai sourcery-ai Bot 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.

Hey - I've left some high level feedback:

  • The repeated TPM/IMA emulator and keylime service setup/cleanup logic across the new test scripts could be consolidated into shared helpers to reduce duplication and make future changes easier.
  • The 600+ line functional/keylimectl-commands/test.sh script is quite large; consider splitting it into smaller, focused test scripts (e.g., policy generation, signing, agent lifecycle) to improve readability and maintainability.
  • Some temporary files (e.g., /tmp/enroll.expect and background HTTP server processes) are created inline in tests; it may be safer to wrap these in helper functions that ensure cleanup on failure to avoid leaking files or processes between runs.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The repeated TPM/IMA emulator and keylime service setup/cleanup logic across the new test scripts could be consolidated into shared helpers to reduce duplication and make future changes easier.
- The 600+ line functional/keylimectl-commands/test.sh script is quite large; consider splitting it into smaller, focused test scripts (e.g., policy generation, signing, agent lifecycle) to improve readability and maintainability.
- Some temporary files (e.g., /tmp/enroll.expect and background HTTP server processes) are created inline in tests; it may be safer to wrap these in helper functions that ensure cleanup on failure to avoid leaking files or processes between runs.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

rlRun "limeWaitForRegistrar"
if [ "${AGENT_SERVICE}" == "PushAgent" ]; then
rlRun "limeUpdateConf verifier mode 'push'"
rlRun "limeUpdateConf verifier push_attestation_period 3"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am afraid that such a low value will be causing issues with test stability, better use >=10.

@kkaarreell kkaarreell left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I do not have any particular requirement, tests look good. At some point would be good to add also some checks for keylimectl console output (where there is only exit code checking).

Also, TF infra seems disrupted ATM but some failing tests seems suspicious (e.g. durable attestation test) because the are passing in other PRs and maybe they could be caused by some changes on the keylime side.

Fix policy sign x509 tests to use -C (--cert-file) instead of -c
(--cert-outfile) for input certificate when -k is provided, matching the
updated keylimectl CLI flags.

Add tests for previously untested commands: policy validate, policy
verify-signature, policy convert, policy merge, info subcommands
(verifier, registrar, agent, tls), configure --non-interactive, and
command aliases (mb for measured-boot, diag for info).

Add tests for agent lifecycle flags: --wait-for-attestation,
--runtime-policy-name, --registrar removal, and --detailed listing.

Add missing help flag tests for verify, verify evidence, policy convert,
policy merge, policy generate tpm, and info subcommands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
rlPhaseStartTest "mb alias for measured-boot"
rlRun "keylimectl mb push testmb-alias --file mb-verifier-policy.json" 0 "Push via mb alias"
rlRun -s "keylimectl mb show testmb-alias"
rlAssertGrep "testmb-alias" $rlRun_LOG
rlRun -s "keylimectl mb show testmb-alias"
rlAssertGrep "testmb-alias" $rlRun_LOG
rlRun -s "keylimectl mb list"
rlAssertGrep "testmb-alias" $rlRun_LOG

rlPhaseStartTest "agent list --detailed"
rlRun -s "keylimectl agent list --detailed"
rlAssertGrep "${AGENT_ID}" $rlRun_LOG
ansasaki and others added 9 commits September 7, 2026 13:10
Use extracted public keys instead of private keys for policy validate
and policy verify-signature tests — these commands require an X.509
certificate or ECDSA public key, not a private key.

Restart the agent service after remove --registrar to trigger immediate
re-registration with the registrar before attempting to re-add the agent
with --runtime-policy-name.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Update policy validate/verify-signature tests to expect exit code 10
(negative result) instead of 1 when using the wrong key. Exit code 1 is
reserved for actual errors (e.g. invalid DSSE envelope).

Use runtime-policy-updated.json for --wait-for-attestation and
--runtime-policy-name tests since the IMA log contains entries from the
earlier "Fail keylime agent" phase that are not in the original
runtime-policy.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
keylimectl now returns exit code 10 (negative result) when:
- Combined agent status query finds the agent not fully attested
  (e.g. in "Get Quote" state)
- Agent status returns not_found after removal

These are intentional keylimectl semantics: exit 0 = positive/success
result, exit 10 = operation succeeded but result is negative.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
In push mode the first attestation cycle takes longer than the
default 20s timeout. Increase limeWaitForAgentStatus timeout to
120s for all attestation_status PASS/FAIL checks.

Also make the combined 'agent status' exit code mode-aware:
- Pull mode: agent is in 'Get Quote' (not fully attested) → exit 10
- Push mode: agent has attested successfully (PASS) → exit 0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
In push mode, the agent accumulates exponential backoff from repeated
failed authentication attempts after the previous 'agent remove'. The
backoff can reach up to 300s, causing the --wait-for-attestation 120s
timeout to expire before the agent retries.

Restart the push agent before this test phase to reset backoff state,
ensuring the agent will attempt authentication promptly after
enrollment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Clean up any leftover measured-boot refstate before pushing in the CRUD
test phase, to handle VMs reused across test runs.

In push mode, regenerate the runtime policy from the current IMA
measurement list before --wait-for-attestation. The IMA log grows
throughout the test run, so the earlier runtime-policy-updated.json no
longer covers all entries by this phase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
…meout

Add pre-test cleanup for testpolicy1 and testmb-alias to handle policies
left behind by a previous failed test run.

Increase --attestation-timeout to 240s for the push model
--wait-for-attestation test. The push model agent's exponential backoff
(10s → 20s → 40s → 80s) means the worst case is ~125s before the agent
successfully attests after a fresh restart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Clean up any leftover testpolicy-named from a previous failed run before
pushing it in the --runtime-policy-name test phase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
…n phase

The IMA emulator adds open-file measurements for the bad script after
the regular IMA measurement. The excludelist for TESTDIR is consumed by
'agent update after failure', so it must be re-applied before generating
runtime-policy-current.json in the --wait-for-attestation phase.

Without this, IMA emulator measurements of the bad script appear after
policy generation and cause 'File not found in allowlist' failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Comment thread functional/keylimectl-commands/test.sh Fixed
ansasaki and others added 3 commits September 11, 2026 14:22
…station policy

Replace limeExtendNextExcludelist with limeSyncIMAExcludelist to exclude
all /keylime-tests/ directories found in the IMA log, not just the
current run's TESTDIR. This covers bad script entries from all previous
test runs that accumulate in the IMA log.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
The IMA emulator adds open-file measurements asynchronously. If new
measurements appear between policy generation and attestation, the
verifier rejects them as 'not in allowlist'.

Fix: stop the push agent first, wait 3s for pending emulator events to
settle, generate the policy (with limeSyncIMAExcludelist to exclude test
directories), then start the agent and enroll. This minimizes the window
for new IMA emulator measurements to appear.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
…r-attestation

limeSyncIMAExcludelist populates the base excludelist file, but
'keylimectl policy generate runtime --ima-measurement-list' wasn't
reading it. Pass the file explicitly with --excludelist so that all
/keylime-tests/ directories (including the bad script) are excluded from
the generated policy and don't cause IMA verification failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Comment thread functional/keylimectl-commands/test.sh Fixed
ansasaki and others added 2 commits September 11, 2026 16:09
Instead of using --excludelist (which requires the verifier to apply
excludes — a feature not yet working in the push model path), generate
the policy from the full IMA measurement list so all current entries
(kernel IMA and emulator) are included in the digests allowlist.

Wait 3s first for the IMA emulator to record pending open-file events
before policy generation, minimizing post-policy emulator measurements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Commands run without rlRun may execute in a different subshell context,
causing them to run at an unexpected time relative to the test commands.
This caused DELETE requests to arrive at the verifier after GET requests
(e.g. deleting testmb1 after show was already in-flight).

Wrap all cleanup delete commands with 'rlRun ... 0-255' to ensure they
execute synchronously and in the correct order relative to the push.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
@ansasaki

Copy link
Copy Markdown
Contributor Author

/packit test

When a file named {section}.conf exists in the config directory, modify
only that file instead of scanning all *.conf files. This prevents
unintended side-effects: e.g. 'limeUpdateConf verifier mode push' was
also modifying keylimectl.conf (which shares [verifier] but uses TOML
format), causing keylimectl to fail to parse the file due to unquoted
INI-style values.

With this fix, if {section}.conf exists the search is limited to that
file only. The fallback (scanning all .conf files) is preserved for
sections without a dedicated file.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
@ansasaki

Copy link
Copy Markdown
Contributor Author

/packit test

2 similar comments
@ansasaki

Copy link
Copy Markdown
Contributor Author

/packit test

@ansasaki

Copy link
Copy Markdown
Contributor Author

/packit test

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.

3 participants