Skip to content

[hooks] Add Barbican secret-store migrate live test hook - #4147

Draft
vakwetu wants to merge 2 commits into
openstack-k8s-operators:mainfrom
vakwetu:feature/OSPRH-35280-secret-store-migrate
Draft

[hooks] Add Barbican secret-store migrate live test hook#4147
vakwetu wants to merge 2 commits into
openstack-k8s-operators:mainfrom
vakwetu:feature/OSPRH-35280-secret-store-migrate

Conversation

@vakwetu

@vakwetu vakwetu commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add a pre_tests hook that live-migrates a Barbican secret between SimpleCrypto and PKCS#11 and asserts the backend in MariaDB.
  • Covers OSC round-trip, barbican-secret-migrate round-trip, dry-run, and metadata-only 409.
  • Playbooks live under hooks/playbooks/barbican-secret-store-migrate/ so they do not clutter hooks/playbooks/.

Prerequisite: the control plane must enable both stores (simple_crypto and pkcs11). Current Luna/Proteccio jobs only enable pkcs11; that is a follow-up in the component job / testproject.

Test plan

  • pre-commit run --all-files (ansible-lint)
  • commit-message body + Signed-off-by
  • Live run via testproject parenting the Luna component job (not in this PR)

Related-Issue: #OSPRH-35280
Related: OSPRH-35261, OSPRH-35331, RHOSSTRAT-1435

Assisted-by: Cursor Grok 4.6

Tempest cannot prove a secret changed backends. This hook creates a
secret on the global default store, migrates it with OSC and
barbican-secret-migrate, and checks MariaDB for the expected plugin.

Related-Issue: #OSPRH-35280

Assisted-by: Cursor Grok 4.6 <noreply@cursor.com>
Signed-off-by: Ade Lee <alee@redhat.com>
@openshift-ci

openshift-ci Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci

openshift-ci Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign eshulman2 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Drop MariaDB/sql checks. Assert placement with openstack secret get
(microversion 1.3 fields). Discover stores via openstacksdk. Keep
admin CLI project-scoped token and pinned payload.

Related-Issue: #OSPRH-35280

Assisted-by: Cursor Grok 4.5
Signed-off-by: Ade Lee <alee@redhat.com>
@vakwetu
vakwetu marked this pull request as ready for review September 2, 2026 20:34
@vakwetu
vakwetu force-pushed the feature/OSPRH-35280-secret-store-migrate branch from 6435806 to 5bcadc7 Compare September 2, 2026 20:34
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add Barbican secret-store migration live-test hook

🧪 Tests ✨ Enhancement 🕐 40+ Minutes

Grey Divider

AI Description

• Adds live migration coverage between SimpleCrypto and PKCS#11 through both supported clients.
• Verifies backend placement through microversion 1.3 metadata while preserving secret payloads.
• Covers round trips, dry runs, metadata-only rejection, and guaranteed cleanup.
Diagram

sequenceDiagram
    actor CI as Hook Runner
    participant OCP as OpenShift API
    participant OSC as OSC Pod
    participant BARB as Barbican API
    participant ADM as Admin CLI
    participant STORES as Secret Stores
    CI->>OCP: Discover pods
    CI->>OSC: Issue token
    OSC->>BARB: List stores
    BARB-->>OSC: Store catalogue
    CI->>OSC: Create and migrate
    OSC->>BARB: OSC requests
    BARB->>STORES: Move payload
    CI->>ADM: Run migration tool
    ADM->>BARB: Admin request
    BARB->>STORES: Move payload
    CI->>OSC: Verify and clean up
    OSC->>BARB: GET metadata v1.3
    BARB-->>OSC: Store ID and payload
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Verify placement through MariaDB
  • ➕ Directly observes Barbican's persisted backend records.
  • ➕ Does not depend on OSC field formatting.
  • ➖ Couples the test to private database schemas and plugin implementation details.
  • ➖ Requires database credentials and Galera pod access.
  • ➖ Bypasses the public API contract exposed by microversion 1.3.
2. Use direct Barbican REST requests
  • ➕ Provides explicit microversion headers and stable JSON field names.
  • ➕ Avoids dependencies on OSC command output formatting.
  • ➖ Duplicates authentication, endpoint discovery, request, and error-handling logic.
  • ➖ Provides less end-to-end coverage of the supported OSC migration workflow.
  • ➖ Still requires a separate mechanism for the administrative CLI path.

Recommendation: Keep the current API-visible verification strategy. Checking secret_store_id through microversion 1.3 validates the supported contract without database coupling, while OSC and barbican-secret-migrate coverage exercises both user-facing migration paths; openstacksdk is a focused workaround for OSC's missing secret-store listing command.

Files changed (5) +678 / -0

Tests (5) +678 / -0
admin.ymlExecute administrative secret migrations inside Barbican +71/-0

Execute administrative secret migrations inside Barbican

• Runs 'barbican-secret-migrate' in the Barbican API container with a project-scoped token and discovered service endpoints. Supports both normal and dry-run execution against a selected secret and destination store.

hooks/playbooks/barbican-secret-store-migrate/admin.yml

assert.ymlAssert secret placement through API metadata +43/-0

Assert secret placement through API metadata

• Retrieves secret metadata with OSC and verifies that microversion 1.3 exposes the expected store ID and href. This confirms backend placement without querying Barbican's database.

hooks/playbooks/barbican-secret-store-migrate/assert.yml

metaonly.ymlCover metadata-only migration rejection +115/-0

Cover metadata-only migration rejection

• Creates a secret without a payload, asserts that migration fails with a bad-request response, and verifies its store fields remain null. An 'always' block removes the test secret even after assertion failures.

hooks/playbooks/barbican-secret-store-migrate/metaonly.yml

migrate.ymlOrchestrate Barbican live migration scenarios +272/-0

Orchestrate Barbican live migration scenarios

• Discovers required pods, service endpoints, credentials, and SimpleCrypto and PKCS#11 store IDs. It then runs OSC and administrative round trips, a dry run, and the metadata-only failure scenario with clear prerequisite checks.

hooks/playbooks/barbican-secret-store-migrate/migrate.yml

one.ymlImplement reusable secret migration lifecycle +177/-0

Implement reusable secret migration lifecycle

• Creates a payload-bearing secret, verifies its source placement, migrates it through the selected client, and checks destination or unchanged placement. Round-trip scenarios also restore the source backend, validate payload integrity, and always delete the secret.

hooks/playbooks/barbican-secret-store-migrate/one.yml

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2) 📜 Skill insights (0)

Grey Divider


Action required

1. Scenario blocks omit rescue 📘 Rule violation ◔ Observability
Description
The complex migration scenarios proceed directly from block to always without a rescue path
that reports failure state and explicitly terminates the run. Failures—particularly those from
no_log tasks—therefore lack the structured diagnostics required by the checklist.
Code

hooks/playbooks/barbican-secret-store-migrate/one.yml[160]

+  always:
Evidence
PR Compliance ID 4 requires complex sequences to use block/rescue/always, emit relevant
variables from rescue, and terminate with ansible.builtin.fail. Both new scenario files define
long multi-operation blocks that transition directly to always cleanup without any rescue
diagnostics.

AGENTS.md: Complex Ansible Task Sequences Must Provide Structured Failure Diagnostics
hooks/playbooks/barbican-secret-store-migrate/one.yml[15-177]
hooks/playbooks/barbican-secret-store-migrate/metaonly.yml[4-115]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The migration scenario blocks have cleanup under `always`, but no `rescue` path that exposes relevant failure context and terminates with `ansible.builtin.fail`.

## Issue Context
Report safe diagnostic fields such as the failed task name, return code, and sanitized stderr. Preserve cleanup in `always` and avoid exposing tokens, payloads, or credentials from `no_log` tasks.

## Fix Focus Areas
- hooks/playbooks/barbican-secret-store-migrate/one.yml[154-177]
- hooks/playbooks/barbican-secret-store-migrate/metaonly.yml[87-115]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Static pod name variable 📘 Rule violation ⚙ Maintainability
Description
cifmw_barbican_migrate_osc_pod_name stores the static value openstackclient and is consumed only
once by the pod lookup. This adds unnecessary indirection without a demonstrated reuse or
configuration benefit.
Code

hooks/playbooks/barbican-secret-store-migrate/migrate.yml[38]

+    cifmw_barbican_migrate_osc_pod_name: openstackclient
Evidence
PR Compliance ID 6 prohibits variables introduced only for static, single-use values. The variable
is assigned openstackclient at line 38 and its only consumer is the name argument of the
openstackclient pod lookup at line 54.

AGENTS.md: Avoid Unnecessary Variables for Single-Use Static Values
hooks/playbooks/barbican-secret-store-migrate/migrate.yml[38-54]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The play introduces a variable solely to hold the single-use static value `openstackclient`.

## Issue Context
Inline the value in the pod lookup. If configurability is required, define an externally overridable default rather than an unconditional play variable and document that configuration purpose.

## Fix Focus Areas
- hooks/playbooks/barbican-secret-store-migrate/migrate.yml[38-54]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Wrong default backend accepted 🐞 Bug ≡ Correctness
Description
The store validation only requires SimpleCrypto, PKCS#11, and one global default, but _store_other
treats every default other than PKCS#11 as SimpleCrypto. If a third backend is global, secrets
migrate from that backend to PKCS#11, so the hook never exercises the required
SimpleCrypto-to-PKCS#11 path.
Code

hooks/playbooks/barbican-secret-store-migrate/migrate.yml[R232-233]

+        _store_src: "{{ _stores_default[0] }}"
+        _store_other: "{{ _stores_simple[0] if _stores_default[0].crypto_plugin == 'p11_crypto' else _stores_pkcs11[0] }}"
Evidence
The assertions only verify one SimpleCrypto store, one PKCS#11 store, and one global default; they
do not constrain that default's crypto_plugin. The following conditional selects PKCS#11 for every
default value other than p11_crypto, while secrets are explicitly created on the global-default
store.

hooks/playbooks/barbican-secret-store-migrate/migrate.yml[278-299]
hooks/playbooks/barbican-secret-store-migrate/one.yml[17-38]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The migration hook accepts a third backend as the global default and then incorrectly treats it as the SimpleCrypto source, leaving the intended SimpleCrypto/PKCS#11 path untested.

## Issue Context
Store validation proves that both target backends exist but does not prove that the global default is one of them. Secret creation uses the global default, so the scenario must reject any other default backend.

## Fix Focus Areas
- hooks/playbooks/barbican-secret-store-migrate/migrate.yml[218-233]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
⚠️ Tickets: not configured — ticket URL found in PR but could not be fetched — check ticket provider credentials
Review mode: ⚖️ Balanced: Downgraded extended -> standard: change is below the extended eligibility bar (hunks 5/18, lines 678/200; both must reach the floor). Router rationale: This adds a substantial live Ansible integration test spanning Kubernetes discovery, authentication, secret migration, backend assertions, cleanup, dry-run, and error handling, with many independent logic paths where a single pass could miss defects.

Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

- _payload_after.stdout | trim == cifmw_barbican_migrate_payload
fail_msg: >-
{{ cifmw_barbican_migrate_case }}: payload mismatch after migrate.
always:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Scenario blocks omit rescue 📘 Rule violation ◔ Observability

The complex migration scenarios proceed directly from block to always without a rescue path
that reports failure state and explicitly terminates the run. Failures—particularly those from
no_log tasks—therefore lack the structured diagnostics required by the checklist.
Agent Prompt
## Issue description
The migration scenario blocks have cleanup under `always`, but no `rescue` path that exposes relevant failure context and terminates with `ansible.builtin.fail`.

## Issue Context
Report safe diagnostic fields such as the failed task name, return code, and sanitized stderr. Preserve cleanup in `always` and avoid exposing tokens, payloads, or credentials from `no_log` tasks.

## Fix Focus Areas
- hooks/playbooks/barbican-secret-store-migrate/one.yml[154-177]
- hooks/playbooks/barbican-secret-store-migrate/metaonly.yml[87-115]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

gather_facts: false
vars:
cifmw_barbican_migrate_namespace: "{{ namespace | default(cifmw_openstack_namespace) | default('openstack') }}"
cifmw_barbican_migrate_db_account: barbican

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Static pod name variable 📘 Rule violation ⚙ Maintainability

cifmw_barbican_migrate_osc_pod_name stores the static value openstackclient and is consumed only
once by the pod lookup. This adds unnecessary indirection without a demonstrated reuse or
configuration benefit.
Agent Prompt
## Issue description
The play introduces a variable solely to hold the single-use static value `openstackclient`.

## Issue Context
Inline the value in the pod lookup. If configurability is required, define an externally overridable default rather than an unconditional play variable and document that configuration purpose.

## Fix Focus Areas
- hooks/playbooks/barbican-secret-store-migrate/migrate.yml[38-54]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +232 to +233
cifmw_barbican_migrate_v1: "{{ (_barbican_url | regex_replace('/$', '')) + ('' if _barbican_url.rstrip('/').endswith('/v1') else '/v1') }}"
vars:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

3. Wrong default backend accepted 🐞 Bug ≡ Correctness

The store validation only requires SimpleCrypto, PKCS#11, and one global default, but _store_other
treats every default other than PKCS#11 as SimpleCrypto. If a third backend is global, secrets
migrate from that backend to PKCS#11, so the hook never exercises the required
SimpleCrypto-to-PKCS#11 path.
Agent Prompt
## Issue description
The migration hook accepts a third backend as the global default and then incorrectly treats it as the SimpleCrypto source, leaving the intended SimpleCrypto/PKCS#11 path untested.

## Issue Context
Store validation proves that both target backends exist but does not prove that the global default is one of them. Secret creation uses the global default, so the scenario must reject any other default backend.

## Fix Focus Areas
- hooks/playbooks/barbican-secret-store-migrate/migrate.yml[218-233]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@vakwetu
vakwetu marked this pull request as draft September 2, 2026 20:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant