# QA Handoff: SSO_Cutover.sh v2.0.0 — `-rollback` Feature **Date:** 2026-04-08 **Author:** Claude (Sonnet 4.6), acting on behalf of Tom Tyler **Status:** Ready for QA **P4 Location:** `//guest/tom_tyler/sw/main/SSO_Cutover/` --- ## Background `SSO_Cutover.sh` is a production script that migrates a Perforce server's human users from LDAP-managed authentication to the Perforce Authentication Service (P4AS), enabling Single Sign-On (SSO). The script was built, tested, and verified by the customer in a copy-of-production sandbox at v1.1.4. After that acceptance test, the customer requested a rollback capability — a way to reverse all cutover changes in an emergency without manually editing ~1000 user records. This is the feature added in v2.0.0. --- ## What Changed in v2.0.0 A new `-rollback` option was added to `SSO_Cutover.sh`. It reverses, in a single command, everything the forward cutover run changed — but only what it actually changed. ### How tracking works During a **live** (`-y`) forward run, the script now records what it did using `p4 key` entries: | Key | Meaning | |-----|---------| | `SSO_Cutover.chg.auth.sso.allow.passwd` | Phase 1 set this configurable | | `SSO_Cutover.chg.auth.sso.nonldap` | Phase 1 set this configurable | | `SSO_Cutover.chg.auth.default.method` | Phase 1 set this configurable | | `SSO_Cutover.chg.extension` | Phase 2 updated the P4AS extension | | `SSO_Cutover.chg.trigger` | Phase 3 added the SSO_default trigger | | `SSO_Cutover.ldap.0.` | Phase 4 changed this user's AuthMethod from ldap→perforce | Phase 2 also saves the original extension config to a file: `$LOGS/SSO_Cutover.extension_backup.p4s` ### What rollback reverses | Rollback Phase | Action | |----------------|--------| | Phase 1 | `configure unset` for each changed configurable; reverts `auth.default.method` to `ldap` | | Phase 2 | Restores the P4AS extension from the backup file | | Phase 3 | Removes `SSO_default` entries from the Triggers table | | Phase 4 | Sets `AuthMethod=ldap` for each user tracked by a `SSO_Cutover.ldap.0.*` key | After a successful live rollback, all tracking keys are deleted (clean slate). ### Rollback constraints (enforced by the script) - `-rollback` **requires** `-y` to actually do anything (dry run by default, same as forward run) - `-g` is **not allowed** with `-rollback` (group is not needed; user set comes from keys) - `-nc`, `-ne`, `-nt`, `-nu` are **not allowed** with `-rollback` (rollback is automatic) - Passwords set during the forward run **cannot** be restored — this is acceptable for this customer because human users authenticate via LDAP and are unaffected by the P4 database password --- ## Proposed Test Environment Use a **P4 Battle School Workshop** training lab instance. These labs have a realistic training data set that can be adapted for this purpose. ### Required data setup (simulate pre-cutover state) The lab needs to be in the state the script expects to find at the *start* of a forward run: 1. **P4AS Extension installed** in opt-in mode The extension (`Auth::loginhook`, name `loginhook-a1`) must exist and be configured with a small set of SSO opt-in users/groups (simulating the pilot phase). The rollback will need to restore this opt-in config, so it must exist and be saved as the baseline. 2. **Configurables at pre-SSO values** - `auth.sso.allow.passwd` — should be `0` or unset - `auth.sso.nonldap` — should be `0` or unset - `auth.default.method` — should be `ldap` 3. **SSO_default trigger absent** The `SSO_default` trigger should not yet be in the Triggers table. 4. **A mix of user AuthMethod values** - Most users: `AuthMethod: ldap` (these should be changed by forward run and restored by rollback) - A handful: `AuthMethod: perforce` already (the simulated pilot/opt-in users — these should be left alone by rollback since `SSO_Cutover.ldap.0.` won't be set for them) 5. **A Non-SSO exempt group** Create a group (e.g. `Non-SSO`) containing at least the `perforce` super user and any simulated automation/robot accounts. 6. **SDP layout** The script sources `/p4/common/bin/p4_vars`. The lab must have a working SDP layout, or the relevant variables (`P4BIN`, `LOGS`, `P4TMP`, etc.) must be set in the environment. `$LOGS` must be a writable directory — this is where the extension backup file lands. --- ## Test Plan Run all tests first as a **dry run** (no `-y`) to verify the preview output looks correct, then repeat as a **live run** (`-y`) to verify actual changes. ### Test 1 — Happy path: forward run ```bash SSO_Cutover.sh -g Non-SSO -y ``` **Verify after:** - `p4 configure show auth.sso.allow.passwd` → `1` - `p4 configure show auth.sso.nonldap` → `1` - `p4 configure show auth.default.method` → `perforce` - `p4 extension --configure Auth::loginhook --name loginhook-a1 -o` → opt-out mode (non-sso-groups: Non-SSO, non-sso-users: perforce, sso-groups/sso-users: none) - `p4 triggers -o` → `SSO_default` entries present - `p4 -ztag -F "%User% %AuthMethod%" users` → all non-exempt users show `perforce` - `p4 keys -e "SSO_Cutover.*"` → tracking keys present - `$LOGS/SSO_Cutover.extension_backup.p4s` → file exists and contains valid opt-in config ### Test 2 — Happy path: rollback dry run ```bash SSO_Cutover.sh -rollback ``` **Verify:** - Output describes what would be reversed with `NO_OP:` prefixes - No actual changes made (configurables, extension, triggers, users all unchanged) - Tracking keys still present ### Test 3 — Happy path: rollback live run ```bash SSO_Cutover.sh -rollback -y ``` **Verify after:** - `p4 configure show auth.sso.allow.passwd` → `0` or unset (original state) - `p4 configure show auth.sso.nonldap` → `0` or unset - `p4 configure show auth.default.method` → `ldap` - Extension back in opt-in mode (diff against original opt-in config) - `p4 triggers -o` → `SSO_default` entries gone - Users whose AuthMethod was changed → back to `ldap` - Users already on `perforce` before the forward run → still `perforce` (untouched) - `p4 keys -e "SSO_Cutover.*"` → all tracking keys deleted ### Test 4 — Idempotency: double rollback Run rollback a second time immediately after Test 3. **Verify:** - Script runs without errors - Output says each phase has nothing to undo ("was not changed by the SSO cutover; skipping") - Exit code 0 ### Test 5 — Partial forward run (phase skipped) Run forward with `-ne` (skip extension processing): ```bash SSO_Cutover.sh -g Non-SSO -ne -y ``` Then run rollback: ```bash SSO_Cutover.sh -rollback -y ``` **Verify:** - Rollback Phase 2 reports "P4AS extension was not changed by the SSO cutover; skipping" - Extension is NOT touched by rollback - Configurables, triggers, and users are properly rolled back ### Test 6 — Invalid option combinations (should all fail with usage errors) ```bash SSO_Cutover.sh -rollback -g Non-SSO # -g not allowed with -rollback SSO_Cutover.sh -rollback -nc # phase-skip not allowed with -rollback SSO_Cutover.sh -rollback -ne SSO_Cutover.sh -rollback -nt SSO_Cutover.sh -rollback -nu ``` **Verify:** Each prints a usage error and exits with code 2. ### Test 7 — Rollback with no prior forward run Attempt rollback on a clean instance with no `SSO_Cutover.*` keys: ```bash SSO_Cutover.sh -rollback -y ``` **Verify:** - Script runs without errors - All phases report "was not changed by the SSO cutover; skipping" - Exit code 0 ### Test 8 — Missing extension backup file After a forward run, delete the extension backup file, then attempt rollback: ```bash rm "$LOGS/SSO_Cutover.extension_backup.p4s" SSO_Cutover.sh -rollback -y ``` **Verify:** - Rollback Phase 2 reports an error: "Extension backup file not found" - Other phases (1, 3, 4) still complete successfully - Exit code reflects 1 error --- ## Files | File | Description | |------|-------------| | `SSO_Cutover.sh` | The script (v2.0.0) | | `SSO_Cutover.command_summary.txt` | Output of `SSO_Cutover.sh -man`; regenerated for v2.0.0 | | `TestUtility-ResetToBaseline.sh` | Pre-existing reset utility (lab only); does not have the rollback precision of the new `-rollback` option | --- ## Notes for the Testing Agent - The script requires an SDP environment. Key variables sourced from `p4_vars`: `P4BIN`, `P4USER`, `LOGS`, `P4TMP`. - ShellCheck passes cleanly on the v2.0.0 script. - The forward-run tracking keys use `NoOp=0` (i.e., `SSO_Cutover.0.` and `SSO_Cutover.ldap.0.`). Dry-run keys (`SSO_Cutover.1.*`) are also cleaned up by rollback but don't gate any rollback logic. - The existing `TestUtility-ResetToBaseline.sh` can be used between test iterations to reset lab state, but note it resets *all* users (not just those tracked by the script) and requires the `BASELINE.extension.p4s` file to exist. It is complementary to, not a replacement for, the new `-rollback` option. - After each live rollback test, re-run the forward cutover to restore SSO state before the next rollback test.