# Secrets Safe & Application Credentials: — Killing Hardcoded Passwords with the API

Source: https://ai.techclick.in/blog_beyondtrust_secrets_safe_aapm
Markdown: https://ai.techclick.in/blog_beyondtrust_secrets_safe_aapm.md
Publisher: Techclick Infosec Pvt Ltd

Kill hardcoded passwords with BeyondTrust: Password Safe API runtime retrieval (curl, PowerShell, Python), Secrets Safe for team secrets, and API-key hygiene.

Secrets Safe &amp; Application Credentials: — Killing Hardcoded Passwords with the API student learning map
                     A visual study map for Secrets Safe &amp; Application Credentials: — Killing Hardcoded Passwords with the API showing learning path, evidence, traps, and practice sequence.

                     TECHCLICK STUDY MAP
                     Secrets Safe &amp; Application Credentials: — Killing...
                     BeyondTrust · learn the flow, prove with evidence, avoid unsafe shortcuts

   1. Start
   🎯 By the end you will be able to

   2. Understand
   Pick where you want to start

   3. Prove
   ① The hardcoded-credential problem...

   4. Practice
   ② The Password Safe API — borrow...

                     How to use this page
                     First build the mental model, then connect the concept to a realistic production decision. Finish by testing yourself.
                     Techclick Infosec Pvt Ltd | ai.techclick.in | Training Contact: WhatsApp +91 92772 29456

             Content-specific feature visual for this lesson: use it as the 60-second map before reading the full detail.

             Most engineers think…

             Most engineers think hardcoded passwords are a discipline problem — add a lint rule, scold the developer in code review, done.

             Wrong — review catches the symptom, never the need. The script still  needs  the secret at runtime, so every "fix" just moves the copy: an env var, a CI variable, a config file outside the repo. The copy still exists, still goes stale at rotation, still leaks. The cure is architectural —  AAPM : the job fetches the credential from Password Safe per run, holds it in memory for minutes, and hands it back. Zero copies at rest means rotation can finally run free.

## ① The hardcoded-credential problem — the password nobody dares to rotate

 Walk through any Indian IT floor and you will find them: a database password inside  deploy.sh , the same one in  config.xml , again in a Jenkins pipeline variable, once more in a crontab, and — because someone was helpful in 2021 — pasted on the team wiki. That is  secret sprawl : one credential, many homes, no owner. Each copy was created for a good reason (the job must authenticate unattended), and each copy is now a door an attacker can open with a single  grep .

 Here is the trap that makes it permanent. The audit team says  rotate that password . But rotating it changes the  target  system only — the five copies keep the old value, so the 02:00 job fails, payments queue up, and the on-call engineer gets paged. After one such night, the team quietly files a rotation exemption. Now the password ages for years, ex-employees still know it, and the one control that would have contained a breach is switched off.  Rotation breaks the script → so nobody rotates → so the secret never dies.  That is the vicious cycle, and no code-review rule can break it.

 👉 So far: copies make rotation scary, so rotation stops — and the password outlives the people who set it. Next: what the diagram of this mess looks like, and the runtime fetch that breaks the loop.

  Figure 1 — One password, five homes — vs no home at all

 Left red zone: one password copied into deploy.sh, config.xml, a Jenkins variable, a crontab and a wiki page, with an attacker reading every copy via grep, and a note that rotating it breaks five things so rotation stays off. Right blue zone: the script stores nothing and fetches from the Password Safe vault at runtime, so the vault rotates nightly and nothing breaks.

- One password, five homes — vs no home at all TODAY — secret sprawl deploy.sh PASS=Mumbai@2019 config.xml same password Jenkins env var same again crontab -l inline copy team wiki pasted in 2021 attacker grep -ri passw rotate it → five things break at 02:00 → so rotation stays OFF, for years five copies at rest = five doors for one thief AAPM — fetch at runtime run.sh no secret inside Password Safe vault + rotation fetch per run minutes, in memory at rest: ZERO copies of the password vault rotates nightly — nothing breaks every fetch = one audit row who · which account · when · from which IP the only thing stored: one scoped API key untrusted/attacker trusted/vaulted policy/decision key insight allowed/audited Left: every red box is a standing copy an attacker can grep; the amber note is the vicious cycle. Right: the script stores nothing — it borrows from the vault per run, so rotation runs nightly and the only thing at rest is one scoped API key. Think of it like the spare key under the flowerpot. The first copy felt convenient; then the maid got one, the neighbour got one, a cousin got one. Now changing the lock means chasing four people with new keys — so the lock is never changed, even after the cousin moved cities. The fix everyone actually wants is the AAPM model: stop distributing keys at all; let each visitor collect a fresh key from the security desk, on camera, and return it on the way out. In BeyondTrust language: the script authenticates to Password Safe with one scoped API key, borrows the real credential for minutes, and never stores it. ### Four words that frame this lesson Tap each card — these four ideas come back in every section. 🔁 The vicious cycle tap to flip Hardcode → copy → rotation breaks copies → rotation disabled → password ages for years. So: the fix is architecture, not discipline. 🌱 Secret sprawl tap to flip One credential quietly multiplies into scripts, configs, pipelines, wikis. Every copy is one more grep away from an attacker. So: count your copies. 🤝 AAPM tap to flip The app fetches from the vault at runtime, holds the secret in memory, gives it back. So: zero copies at rest. 💥 Blast radius tap to flip A leaked secret is bounded by what it reaches and how long it lives. Short release windows and a scoped runas shrink both. So: scope everything. Sneha at Infosys faces this Audit forced Automatic Password Management ON for svc_recon on PAY-APP-03 (172.16.8.31). The vault rotated it at 23:30 UTC. At 02:00 the reconciliation cron failed with "Login failed for user svc_recon" and three downstream jobs queued behind it. Likely cause The old password is hardcoded in /opt/recon/run.sh, one config file and a Jenkins variable — rotation changed the target system, not the copies. Diagnosis grep -r for the account name across the repo and Jenkins finds three standing copies; the Managed Accounts grid shows Last Change Date = last night, so the rotation fired exactly as designed. BeyondInsight > Managed Accounts > svc_recon (Last Change Date / rotation history) Fix Convert the job to runtime retrieval: create an API registration plus a runas user holding the Requestor role on svc_recon, make run.sh call SignAppin → Requests → Credentials → checkin each run, then delete every stored copy. Verify Force one more rotation, re-run the cron by hand — it authenticates with the fresh secret. Rotation is now free to run nightly without a single page. Quick check · Q1 of 10 Aditya at TCS finds svc_eod’s password unchanged since 2021, although Password Safe is licensed and Automatic Password Management works fine elsewhere. What is the most likely reason rotation is OFF for this account? a) The vault cannot rotate service accounts at all b) The same password is hardcoded in scripts and pipeline variables — one rotation breaks them all, so the team disabled it c) Rotation only works on Windows accounts d) The password policy expired in 2021 Correct: b. The vicious cycle: standing copies make rotation a guaranteed outage, so teams file exemptions and rotation is switched off. (a) is false — service accounts rotate fine when nothing hardcodes them; (c) is false — Unix/Linux, databases and network devices are all supported platforms; (d) password policies govern how new passwords are generated, they do not silently stop rotation. Pause & Predict Predict: ICICI’s auditor forces a rotation of svc_corebank tonight at 23:30 UTC. The password is hardcoded in four scripts. Describe Monday morning. Type your guess. Reveal answer Answer: At 02:00 the first job fails to authenticate; everything downstream queues. On-call either restores the OLD password (defeating the audit) or hot-patches four scripts at 3 a.m. By Monday the team requests a rotation exemption — and the vicious cycle completes. The only durable fix is removing the copies: runtime retrieval via the API. ## ② The Password Safe API — borrow the credential, never store it Everything starts with an API registration . In BeyondInsight you create one under Configuration → General → API Registrations : it issues a 128-character key and lets you attach Authentication Rules (allowed source IPs) and options like User Password Required . The key alone is not an identity — every call also names a runas user, and that user’s roles (Requestor, Requestor/Approver, ISA ) decide what the call may touch. Two more facts worth an interview answer: there is an OAuth client-credentials alternative for application-type users under an API Access Policy registration, and client certificates are being phased out as an API-registration auth method in the 25.x line — plan new automation on keys or OAuth, not certs. BeyondInsight → Configuration → General → API Registrations → Create API Registration . (Recreated for clarity — your console matches this.)"> 🖥️ This is the screen you’ll create the key on — BeyondInsight → Configuration → General → API Registrations → Create API Registration . (Recreated for clarity — your console matches this.) bi.icicilab.example · Configuration → API Registrations 1 Registration Name jenkins-cred-fetch 2 Registration Type API Key Policy 3 Authentication Rule IP Address · 10.20.30.41 (Jenkins runner only) User Password Required Off — key + runas only Client Certificate Required Off (deprecated as API auth in 25.x) 4 API Key c479a66f83… (128 chars — copy once, vault it) Create Registration The header format is the thing students copy wrong most often, so read it once carefully: Authorization: PS-Auth key= ; runas= ; pwd=[ ]; — the password sits in square brackets and appears only if the registration demands it. POST Auth/SignAppin opens a session (state is kept between calls), POST Auth/Signout closes it. Think Aadhaar OTP: nobody memorises a permanent code — each transaction gets a fresh, short-lived secret, so yesterday’s stolen OTP buys the thief nothing. Runtime retrieval gives your scripts the same property. Figure 2 — Four calls — borrow, use, give back, rotate Two swimlanes. Left lane is your job at 10.20.30.41, right lane is Password Safe behind the slash BeyondTrust slash api slash public slash v3 base path. Four numbered exchanges flow between them: SignAppin with key and runas, POST Requests which passes an amber access-policy and role check and returns request ID 4172, GET Credentials 4172 returning the secret into process memory only, and PUT checkin after which the vault rotates the password because Change Password After Release is set. Four calls — borrow, use, give back, rotate your job 10.20.30.41 · svc-jenkins-api Password Safe /BeyondTrust/api/public/v3 ① POST Auth/SignAppin · PS-Auth key + runas ② POST Requests {SystemId 57, AccountId 214} access policy + role check Requestor / ISA on the account? RequestId 4172 · approved for 10 min ③ GET Credentials/4172 → secret secret lives ONLY in process memory ④ PUT Requests/4172/checkin · POST Auth/Signout Change Password After Release → vault rotates untrusted/attacker trusted/vaulted policy/decision key insight allowed/audited Follow the numbered arrows: SignAppin authenticates the job, Requests passes the amber access-policy + role gate, Credentials hands over the secret (memory only), and check-in lets Change Password After Release rotate it. The job never stores anything. curl — sign in, then find the account (Password Safe REST API) # 1) sign in — key from the API registration, runas = a real Password Safe user curl -s -c /tmp/ps.cookies -X POST \ -H "Authorization: PS-Auth key=c479a66f83…9484d; runas=icici\svc-jenkins-api;" \ "https://bi.icicilab.example/BeyondTrust/api/public/v3/Auth/SignAppin" # 2) find the account (works ONLY when Enable for API Access is ON) curl -s -b /tmp/ps.cookies \ -H "Authorization: PS-Auth key=c479a66f83…9484d; runas=icici\svc-jenkins-api;" \ "https://bi.icicilab.example/BeyondTrust/api/public/v3/ManagedAccounts?systemName=PAY-DB-01&accountName=svc_corebank" Expected output {"UserId":318,"UserName":"icici\svc-jenkins-api","Name":"Jenkins API user"} {"PlatformID":4,"SystemId":57,"SystemName":"PAY-DB-01","AccountId":214, "AccountName":"svc_corebank","DefaultReleaseDuration":120, "MaximumReleaseDuration":525600} ← SystemId + AccountId feed the next call ### ▶ One credential fetch, start to finish Watch a Jenkins job borrow svc_corebank for ten minutes and give it back. Press Play for the healthy path, then Break it to see the failure. ① SignAppin svc-jenkins-api → POST Auth/SignAppin · PS-Auth key + runas ▼ ② Request POST Requests {SystemId 57, AccountId 214} → RequestId 4172 ▼ ③ Retrieve GET Credentials/4172 → secret in process memory only ▼ ④ Check-in PUT Requests/4172/checkin → vault rotates per policy Press Play to step through the healthy path. Then press Break it . ▶ Play Next ▶ ⚠ Break it ↺ Reset PowerShell — full borrow-use-return cycle (Requests workflow) $base = 'https://bi.icicilab.example/BeyondTrust/api/public/v3' $h = @{ Authorization = 'PS-Auth key=c479a66f83…9484d; runas=icici\svc-jenkins-api;' } Invoke-RestMethod "$base/Auth/SignAppin" -Method Post -Headers $h -SessionVariable ps | Out-Null $acct = Invoke-RestMethod "$base/ManagedAccounts?systemName=PAY-DB-01&accountName=svc_corebank" -WebSession $ps -Headers $h $req = Invoke-RestMethod "$base/Requests" -Method Post -WebSession $ps -Headers $h -ContentType 'application/json' -Body (@{ SystemId = $acct.SystemId; AccountId = $acct.AccountId DurationMinutes = 10; Reason = 'Nightly reconciliation run' } | ConvertTo-Json) $secret = Invoke-RestMethod "$base/Credentials/$req" -WebSession $ps -Headers $h # …use $secret in memory only, then hand it back: Invoke-RestMethod "$base/Requests/$req/checkin" -Method Put -WebSession $ps -Headers $h -ContentType 'application/json' -Body '{}' Invoke-RestMethod "$base/Auth/Signout" -Method Post -WebSession $ps -Headers $h Expected output 4172 ← POST Requests returns just the request ID vY8#kQz2!mNp4@Lr9wTe6 ← GET Credentials/4172 — the live secret ← checkin + Signout answer 204 No Content (vault now rotates per policy — your stored-copy count stays ZERO) Python — unattended job with the ISA role (no approval hop) import requests BASE = 'https://bi.icicilab.example/BeyondTrust/api/public/v3' HDR = {'Authorization': 'PS-Auth key=c479a66f83…9484d; runas=icici\\svc-isa-eod;'} s = requests.Session() s.post(f'{BASE}/Auth/SignAppin', headers=HDR).raise_for_status() # ISA role = instant release: ONE call returns the credential itself r = s.post(f'{BASE}/ISARequests', headers=HDR, json={ 'SystemId': 57, 'AccountId': 214, 'DurationMinutes': 10, 'Reason': 'EOD reconciliation 02:00 IST'}) secret = r.json() # str — held in memory, never written to disk s.post(f'{BASE}/Auth/Signout', headers=HDR) Expected output 201 ← ISARequests: created, credential in the body secret length: 24 ← print(len(secret)) — value itself never logged 204 ← Signout process exits → nothing persists on disk, in env vars, or in CI logs MISTAKE — 200 OK but an empty list Symptom: GET ManagedAccounts answers 200 with [] although the account is clearly onboarded. Three causes, in order of likelihood: Enable for API Access is off on the managed account; the runas user lacks a Requestor / Requestor-Approver / ISA role on it; a directory account was queried without UPN or DOMAIN\account format. Check the setting, the role, the format — in that order. TIP — the 401 that is not an error If the runas user has 2FA enabled, the FIRST SignAppin deliberately answers 401 with a WWW-Authenticate-2FA header — that is the challenge, not a failure. Resend SignAppin with challenge= ; appended to the PS-Auth header, keeping the same session. And treat the API key itself with the respect of the password it replaced: it IS a password. 👉 So far: SignAppin opens the session, Requests + Credentials hand you the secret, check-in lets the vault rotate freely — consumers always fetch fresh. Next: the secrets that have no managed system behind them at all. Quick check · Q2 of 10 Meera at HCL wires up a new API user with 2FA enabled. Her first POST Auth/SignAppin returns 401 with a WWW-Authenticate-2FA header. What should her script do? a) Treat it as a lockout and alert the SOC b) Retry the identical call — it is a transient error c) Send SignAppin again with challenge=  appended to the PS-Auth header, keeping the session d) Switch to the SSH proxy on port 4422 instead Correct: c. The 401 + WWW-Authenticate-2FA pair is the designed two-step challenge: the second SignAppin carries challenge=  in the same header. (a) wastes a SOC ticket on expected behaviour; (b) the identical call will 401 forever; (d) port 4422 is the session proxy for humans opening SSH sessions — unrelated to API auth. Pause & Predict Predict: Rahul at Wipro gets 200 OK with an empty array from GET ManagedAccounts, but the account exists in the console. Name the two most likely causes before you peek. Type your guess. Reveal answer Answer: One: the managed account does not have Enable for API Access ticked — it is invisible to the API. Two: the runas user has no Requestor / Requestor-Approver / ISA role on that account. (Bonus third: a domain account queried without UPN or DOMAIN\account format.) None of these return an error — just an empty list, which is why this bites so many first integrations. ## ③ Secrets Safe — the team almirah for secrets with no machine behind them Not every secret is a login on a server. A Razorpay webhook signing secret, a wildcard TLS certificate (.pfx), a Brevo API token, a licence file — none of these has a managed system Password Safe could rotate against. For these, BeyondInsight ships Secrets Safe (left menu → Secrets Safe ). The model is teams: administrators assign BeyondInsight groups to teams, and each team gets an isolated store. Root folders are called safes , with folder trees underneath — the API returns a FolderPath with / as the separator. Three secret shapes cover practically everything: a credential (username + password pair), a text secret (tokens, connection strings), and a file (certificates, keytabs, licence blobs). Every entry carries metadata — owner, created and modified dates, folder path — so six months later you know whose token that is. Think of the family Godrej almirah with per-member shelves: the bank locker (Password Safe) holds the property papers that need dual keys and a register; the almirah at home holds the everyday valuables each family member owns — still locked, still accounted for, but organised by shelf, not by bank procedure. BeyondInsight → Secrets Safe → (your team’s safe) → Add Secret . (Recreated for clarity — your console matches this.)"> 🖥️ Adding a team secret — BeyondInsight → Secrets Safe → (your team’s safe) → Add Secret . (Recreated for clarity — your console matches this.) bi.icicilab.example · Secrets Safe 1 Secret Type Text 2 Title razorpay-webhook-secret 3 Folder DevOps/Payments Text whsec_•••••••••••• 4 Owner Team: payments-devops (BeyondInsight group) Create Secret curl — Secrets Safe: read a team text secret by path + title AUTH="Authorization: PS-Auth key=c479a66f83…9484d; runas=icici\svc-gitlab;" # list by folder path + title (path separator is /) curl -s -b /tmp/ps.cookies -H "$AUTH" \ "https://bi.icicilab.example/BeyondTrust/api/public/v3/secrets-safe/secrets?path=DevOps/Payments&title=razorpay-webhook-secret" # read the text value by the secret's GUID curl -s -b /tmp/ps.cookies -H "$AUTH" \ "https://bi.icicilab.example/BeyondTrust/api/public/v3/secrets-safe/secrets/8b1c2e54-77aa-4c1d-9f0e-3d2b6a91c4f7/text" Expected output [{"Id":"8b1c2e54-77aa-4c1d-9f0e-3d2b6a91c4f7","Title":"razorpay-webhook-secret", "Path":"DevOps/Payments","FolderPath":"DevOps/Payments"}] "whsec_9hP2kL…K7tQ" ← the value — pipe it straight into the app, store nothing Figure 3 — Three stores — match the secret to the shelf Three columns compare a Password Safe managed account, a Secrets Safe entry, and a developer-oriented vault such as HashiCorp Vault. Rows cover what each stores, whether it rotates, who consumes it, and when to pick it. A bottom rule of thumb says: machine credential with a system behind it goes to a managed account, shared team token or certificate goes to Secrets Safe, throwaway dynamic credentials for ephemeral infrastructure go to a dev secrets engine. Three stores — match the secret to the shelf Managed account stores: privileged creds WITH a managed system behind them rotation: YES — functional account + Password Change Agent consumers: humans (checkout/session) + apps via the API pick when: svc_corebank on PAY-DB-01, root on 192.168.40.17, sa on a DB Secrets Safe stores: team/app secrets with NO system: API tokens · certs · text · files rotation: NO engine — rotate at the source, update the entry consumers: teams = BeyondInsight groups, safes → folders, owned + audited pick when: Razorpay webhook secret, wildcard .pfx, Brevo API token Dev vault (e.g. HashiCorp) stores: dynamic secrets engines — creds minted per lease rotation: N/A — secrets are born short-lived, then expire consumers: code + ephemeral infra; YOU run and patch the tool pick when: throwaway DB creds for test containers, K8s-native flows Rule of thumb: system behind it → managed account · shared token/cert/file → Secrets Safe · minted-and-destroyed-in-minutes → dynamic dev engine. Audit story: PAM keeps one pane. Read each column top to bottom: what it stores, whether it rotates, who consumes it, when to pick it. The deciding question is always the first row — is there a managed system behind this secret? So when do you pick which? Managed account when a system + functional account exist behind the credential — you get the rotation engine, sessions and check-in for free. Secrets Safe when the secret is a thing your team shares but no rotation engine can touch — provider tokens, certs, files — and you want PAM-grade ownership and audit in the same console your vault lives in. A dev tool like HashiCorp Vault earns its place when engineering needs dynamic secrets — database credentials minted per lease for a test container and destroyed minutes later — or deep Kubernetes-native workflows; the trade-off is that you now operate, patch and audit a second secrets platform. Many Indian enterprises run both: Password Safe + Secrets Safe as the governed system of record, a dev vault inside the platform team’s cluster — with the dev vault’s own root credentials parked… in Password Safe. VERIFY — is this secret on the right shelf? Ask three questions. ① Is there a managed system + functional account behind it? Yes → managed account, so rotation works. ② Is it a shared team artefact a provider rotates (token, cert, file)? Yes → Secrets Safe, owned by a BeyondInsight group. ③ Is it created and destroyed in minutes by ephemeral infra? Yes → that is dynamic-secrets territory, a dev engine’s job. If you answered yes twice, the FIRST yes wins. 👉 So far: machine creds → managed accounts (rotation engine); team tokens, certs, files → Secrets Safe safes and folders; minted-per-lease creds → a dev engine. Next: wiring all of this into CI/CD without quietly creating a new key-shaped hole. Quick check · Q3 of 10 Karthik’s team at Flipkart shares a wildcard TLS certificate (.pfx file) and a Brevo API token. Neither has a managed system behind it. Where do they belong? a) Secrets Safe — a file secret and a text secret in the team’s safe, owned by a BeyondInsight group b) Managed accounts — onboard them with a functional account c) A shared OneNote protected by the team password d) Hardcode them — certificates are public information anyway Correct: a. No managed system = nothing for the rotation engine to act on, so a managed account (b) is the wrong shape — there is no platform to onboard. Secrets Safe exists exactly for this: file + text secrets, safe/folder structure, group ownership, full audit. (c) is sprawl with extra steps; (d) confuses the public certificate with the PRIVATE key inside a .pfx — that key is a crown jewel. Pause & Predict Predict: a developer asks for the team’s Razorpay token "just once, over WhatsApp". What does the Secrets Safe version of this favour look like? Type your guess. Reveal answer Answer: The token lives as a text secret in DevOps/Payments inside the team’s safe. The developer’s BeyondInsight group already grants read — they fetch it from the console or the secrets-safe API, and the access lands in the audit trail with their name on it. The WhatsApp copy, by contrast, is an untracked, unrevokable clone on two phones and a backup. Same favour, zero sprawl. ## ④ DevOps patterns + API hygiene — protect the key that opens the vault The CI/CD pattern is the same everywhere — GitLab CI, Jenkins, GitHub Actions, Azure DevOps: the runner’s secret store holds exactly one secret (the API key), and every job fetches per run with a short DurationMinutes , uses the value from an environment variable that dies with the process, checks the request back in, and signs out. No masked pipeline variables full of passwords, no echo $DB_PASS in the log, no artefact files. Short-lived retrieval beats caching every single time: a cache is a copy, and a copy is exactly the thing this whole lesson kills. CI/CD — fetch-cred.sh runs inside the job; only the API key is injected #!/usr/bin/env bash # Only PS_API_KEY comes from the runner's secret store. # The DB password itself is never stored anywhere. set -euo pipefail BASE='https://bi.icicilab.example/BeyondTrust/api/public/v3' AUTH="Authorization: PS-Auth key=${PS_API_KEY}; runas=icici\svc-gitlab;" CJ=$(mktemp) curl -sf -c "$CJ" -H "$AUTH" -X POST "$BASE/Auth/SignAppin" >/dev/null REQ=$(curl -sf -b "$CJ" -H "$AUTH" -H 'Content-Type: application/json' \ -d '{"SystemId":57,"AccountId":214,"DurationMinutes":5,"Reason":"CI deploy"}' \ -X POST "$BASE/Requests") export DB_PASS=$(curl -sf -b "$CJ" -H "$AUTH" "$BASE/Credentials/$REQ" | tr -d '"') ./deploy.sh # reads DB_PASS from the environment — in memory, this run only curl -sf -b "$CJ" -H "$AUTH" -X PUT "$BASE/Requests/$REQ/checkin" -H 'Content-Type: application/json' -d '{}' curl -sf -b "$CJ" -H "$AUTH" -X POST "$BASE/Auth/Signout" Expected output deploy.sh: connected to PAY-DB-01 as svc_corebank deploy.sh: schema migration 042 applied checked in request 5217 — vault rotates per policy job log shows ZERO secrets — only the request ID MISTAKE — caching the fetch "to save API calls" Symptom: someone optimises the pipeline by writing the fetched password into a CI variable; weeks later every job fails just after 23:30 UTC. Cause: the cached fetch is a brand-new hardcoded copy — it went stale at the next scheduled rotation, exactly like the script copies in section ①. Fix: fetch per run with DurationMinutes 5–10 and check in immediately after use. The API round-trip costs milliseconds; the outage costs a night. Now the uncomfortable part: your automation is only as safe as the key it authenticates with. In December 2024 , attackers stole a Remote Support SaaS API key from BeyondTrust itself , used it to reset local application passwords, and reached 17 SaaS customers — including the US Treasury, where workstations in OFAC and CFIUS were accessed. BeyondTrust detected anomalous behaviour on Dec 5, revoked the key on Dec 8, and the incident was publicly attributed to the Silk Typhoon group. Two lessons transfer directly to your Password Safe registrations. First: MFA would not have helped — an API key authenticates machine-to-machine, outside any interactive MFA path; machine credentials need their own controls. Second: one leaked key = every credential its runas can reach, so the scope of the runas user IS your blast radius . Karthik at Flipkart faces this API logs show successful SignAppin calls for runas flipkart\svc-ci-fetch from 203.0.113.77 at 03:14 — an address that belongs to no Flipkart office or runner. Likely cause A developer committed the 128-character API key to a public GitHub repo inside a helper script. The registration had no Authentication Rule, and the runas user held ISA on 40 accounts — worst-case scope. Diagnosis Repo secret-scan finds the key in git history; the registration audit shows zero IP Authentication Rules; role review shows ISA far beyond what the pipeline needs. BeyondInsight > Configuration > General > API Registrations > svc-ci-fetch Fix Treat the old key as burned: regenerate it, add Authentication Rules pinning the CI runner IPs (10.20.30.0/24), demote the runas to Requestor on only the accounts the pipeline touches, and rotate every credential the old key could have read. Verify Replay SignAppin from an outside address — refused; from the runner subnet — 200. After 24 hours the API log shows runner IPs only, and the rotation report confirms every reachable credential changed. Turn that into a standing routine. Scope : one registration per consumer (Jenkins ≠ GitLab ≠ the monitoring poller), each with its own runas holding the minimum role on the minimum accounts. Restrict : Authentication Rules on every registration — a key that only works from 10.20.30.41 is nearly worthless on GitHub. Rotate the keys themselves : regenerating a registration key is a console action on the API Registrations page — no engine rotates it for you, so put it on the calendar like a certificate renewal, and park the key in Secrets Safe so the handover is owned and audited. Watch : review which IPs sign in as your automation users; the Treasury incident was caught by exactly that kind of anomaly. The hotel master-key register is the right mental model — the master key exists, but every issue and return is written down, and a missing entry is itself the alarm. Figure 4 — API quick-card — pin this above your desk A dark reference card. Top: the base path slash BeyondTrust slash api slash public slash v3 and the PS-Auth header format with key, runas and optional pwd. Middle: eight endpoints — SignAppin, Signout, ManagedAccounts, Requests, Credentials by request ID, ISARequests, secrets-safe secrets by path and title, and secrets-safe text. Right: response codes 200, 201, 204, 401 with the 2FA challenge header, 403 and 404. Bottom: four amber hygiene rules — IP authentication rules, least-privilege runas, regenerate keys on a calendar, fetch per run and never cache. API quick-card — pin this above your desk BASE PATH https://HOST/BeyondTrust/api/public/v3 AUTH HEADER (every call) Authorization: PS-Auth key=…; runas=DOMAIN\user; pwd=[…]; pwd only if the registration demands it · 2FA: resend SignAppin with challenge=code THE 8 CALLS POST Auth/SignAppin → open session GET ManagedAccounts?… → find SystemId/AccountId POST Requests → returns RequestId GET Credentials/{id} → the secret PUT Requests/{id}/checkin → give it back POST ISARequests → ISA: secret in ONE call GET secrets-safe/secrets?path=…&title=… GET secrets-safe/secrets/{guid}/text · POST Auth/Signout RESPONSE CODES 200 OK · 201 created 204 no content (checkin) 401 + WWW-Authenticate-2FA = designed 2FA challenge, not an error 403 role / IP rule refused 404 wrong path or ID HYGIENE — ① IP Authentication Rules on every registration ② least-privilege runas ③ regenerate keys on a calendar (console action — nothing rotates them for you) ④ fetch per run, never cache refused allowed Everything from this lesson on one card: base path, header anatomy, the eight calls, the response codes that confuse beginners (401-2FA is a challenge, not an error), and the four hygiene rules. 🎮 Hands-on: BeyondTrust PAM Essentials room 📼 Sibling lesson: Password Safe Session Management 👉 Full circle: scripts fetch fresh so the vault rotates nightly, team secrets live in owned safes, and the API key itself is scoped, IP-locked, calendar-rotated and watched. That is AAPM done properly — zero standing passwords, one accountable key. Quick check · Q4 of 10 December 2024: a stolen Remote Support SaaS API key let attackers reach 17 customers, including the US Treasury. Which combination would most limit the same blast radius on YOUR Password Safe registration? a) A longer API key string b) MFA on all human console logins c) A stronger password policy on managed accounts d) IP Authentication Rules on the registration + a least-privilege runas + scheduled key regeneration Correct: d. Blast radius = where the key works from × what its runas can reach × how long it stays valid — exactly the three controls in (d). (a) length does not matter once the key is copied; (b) MFA guards interactive humans, and the stolen key authenticated machine-to-machine outside that path; (c) rotating managed-account passwords does not stop a key that can simply fetch the new ones. Pause & Predict Predict: your CI stores the fetched password as a masked pipeline variable "to save API calls". What breaks, and exactly when? Type your guess. Reveal answer Answer: It breaks at the next scheduled rotation — typically just after 23:30 UTC — because the cached value is now a stale hardcoded copy. Worse, masked variables leak: they appear in variable exports, debug reruns and forked-pipeline tricks. You have rebuilt section ①’s problem inside a shinier tool. Fetch per run, DurationMinutes 5, check in, sign out. ### 🤖 Ask the AI Tutor Tap any question — instant, scoped to this lesson. No login, no waiting. Why not just use env vars? When does PS-Auth need pwd=[…]? Requests vs ISARequests — which for automation? Secrets Safe vs HashiCorp Vault? My API key leaked — first 30 minutes? Can Secrets Safe rotate my tokens? Pre-curated from BeyondTrust docs + community Q&A, scoped to this lesson. For a live prod issue, paste your export into chat.techclick.in. ## 📝 Wrap-up assessment — six more You've answered 4 inline. Six left. 70% (7 of 10) marks the lesson complete on your profile. Tap Submit all answers at the end. Q5 · Remember What is the base path of the BeyondInsight / Password Safe public API? a) /BeyondTrust/api/public/v3 b) /api/v1/passwordsafe c) /rest/v2/vault d) /psapi/v3/public Correct: a. The public API lives at https:// /BeyondTrust/api/public/v3 on-prem and cloud alike — it appears in every call this lesson made. The other three are plausible-looking inventions; if you typed them you would meet 404s, which is also why "404 = wrong path" sits on the cheat-card. Q6 · Apply Rahul’s Python job calls GET ManagedAccounts?systemName=PAY-DB-01&accountName=svc_corebank and receives 200 with an empty result, although the account exists in the console. What should he fix first? a) Reboot the U-Series appliance b) Add the runas user to Domain Admins c) Move the ChangeTime away from 23:30 UTC d) Tick Enable for API Access on the account and confirm the runas user holds a Requestor or ISA role on it Correct: d. GET ManagedAccounts only returns accounts that are API-enabled AND visible to the caller’s role — failing either gives a silent empty list, not an error. (a) is cargo-cult ops; (b) violates least privilege and changes nothing about API visibility; (c) ChangeTime is the rotation schedule, unrelated to account listing. Q7 · Apply Priya’s 02:00 unattended job at ICICI cannot wait for a human approver. Which call returns the credential in a single step, by design? a) POST Requests with Reason="urgent" b) POST ISARequests from a runas user holding the ISA role c) GET Credentials without any request d) PUT Requests/{id}/checkin Correct: b. ISA (Information Systems Administrator) is the approval-less role: POST ISARequests returns the credential directly. (a) the Reason text never bypasses an approval chain — only the access policy decides auto-approval; (c) Credentials requires an existing approved RequestId; (d) check-in RETURNS a credential you already hold — it ends access, it does not grant it. Q8 · Analyze Why does runtime retrieval END the rotation deadlock, while a cached copy quietly restarts it? a) Cached copies use weaker encryption than the vault b) Runtime retrieval is faster than reading a config file c) Fetch-fresh consumers always hold the CURRENT secret, so the vault can rotate any time; a cache is a new hardcoded copy that goes stale at the very next rotation d) The API refuses to serve consumers that cache Correct: c. The deadlock exists because standing copies and rotation cannot coexist. Fetch-fresh removes the standing copy, so rotation stops being scary — that is the entire architecture. (a) encryption strength is irrelevant to staleness; (b) it is actually slower by milliseconds, and that does not matter; (d) the API cannot know or police what a consumer does with the value — only your design can. Q9 · Analyze In the December 2024 Treasury incident, why would MFA on console logins NOT have stopped the attacker? a) The stolen API key authenticated machine-to-machine, outside any interactive MFA path — machine credentials need their own controls: scoping, IP rules, regeneration, usage monitoring b) Treasury had configured MFA incorrectly c) The attackers phished the one-time codes as well d) API keys disable HTTPS, so MFA is bypassed in transit Correct: a. MFA protects a human at a login prompt; an API key never sees one — the Dec-2024 attackers used a stolen Remote Support SaaS key to act as the service itself. (b) and (c) describe failure modes that were not part of this incident; (d) is nonsense — the API is HTTPS-only, and transport security was never the issue. The transferable lesson: inventory and guard your machine credentials separately from human auth. Q10 · Evaluate ICICI’s architect must place three workloads: 600 rotating service-account passwords, 40 team-shared API tokens and certificates, and throwaway database creds for ephemeral test containers. Evaluate the best split. a) Everything into managed accounts — one tool, one truth b) Managed accounts for the 600 service accounts; Secrets Safe for the 40 tokens and certs; a dynamic-secrets dev engine for the throwaway container creds c) Everything into Secrets Safe to avoid configuring functional accounts d) Everything into a self-hosted dev vault, because it has no licence cost Correct: b. Each store matches a lifecycle: rotating machine creds need the functional-account rotation engine (managed accounts); shared tokens/certs have no system to rotate against and need owned, audited shelves (Secrets Safe); minted-and-destroyed creds are what dynamic engines exist for. (a) breaks on the 40 tokens — no managed system exists; (c) throws away rotation for 600 accounts, recreating the stale-password problem at scale; (d) ignores that "free" means you now run, patch, audit and HA a second Tier-0 platform — and its root creds still need a vault. Submit all answers Try again Lesson complete — saved to your profile. Almost! You need 70% (7 of 10) — re-read the path that tripped you up and tap "Try again". ### 🧠 In your own words Type one line: Your manager asks: we already keep passwords in the Jenkins credentials store — why do we need AAPM and Secrets Safe? Then compare to the expert version. Compare with expert answer Expert version: Jenkins encrypts secrets at rest, but they are still standing copies: they never change when the vault rotates, any job that prints its environment can leak them, and nobody can answer who used what, when. With AAPM the job fetches the credential from Password Safe at runtime — so the vault rotates nightly and nothing breaks, every fetch is an audit row tied to a runas identity, and a stolen Jenkins export contains no passwords at all. Jenkins keeps exactly one secret: an IP-locked, least-privilege API key. Team-shared tokens and certificates that Jenkins never touches move to Secrets Safe, owned by a BeyondInsight group instead of a WhatsApp thread. ### 🗣 Teach a friend Best way to lock it in — explain it in one line to a teammate. Tap to generate a paste-ready summary. Generate my one-liner 📩 Quiz me on this in 7 days. Opt in and we'll email 3 micro-questions on Secrets & App Credentials at Day 1, Day 7 and Day 30 — spaced repetition is how this sticks. Un-tick any time. ### 📖 Glossary AAPM Application-to-Application Password Management — apps fetch credentials from the vault at runtime instead of storing their own copy. Secret sprawl The same credential copied across scripts, configs and pipelines until nobody can safely rotate it. API registration BeyondInsight object that issues a 128-character API key plus caller rules (source IP, password, 2FA). PS-Auth The API Authorization header scheme: key=…; runas=…; pwd=[…]; — key identifies the registration, runas the acting user. runas The Password Safe user an API call acts as; its roles decide exactly what that key can touch. ISA Information Systems Administrator role — instant, approval-free credential release via POST ISARequests. Enable for API Access Managed-account setting; without it the account is invisible to GET ManagedAccounts. Secrets Safe BeyondInsight store for team and application secrets — credentials, text, files — in safes and folders; no rotation engine. Safe A root folder in Secrets Safe; each team (a BeyondInsight group) gets its own isolated safe. Check-in Returning a released credential; with Change Password After Release set, the vault rotates it immediately. OAuth client credentials Alternative API auth for application-type users under an API Access Policy registration — token-based, no PS-Auth key header. #### 📚 Sources BeyondInsight & Password Safe API usage — PS-Auth header (key/runas/pwd), SignAppin/Signout, 2FA challenge, OAuth client credentials. docs.beyondtrust.com/bips/reference/beyondinsight-and-password-safe-api-usage

- Password Safe API endpoint catalog — Auth, ManagedAccounts, Requests, ISARequests, Credentials + defaults (120 / 525600 / 23:30). docs.beyondtrust.com/bips/v24.3/docs/password-safe-api

- Secrets Safe — teams as BeyondInsight groups, safes (root folders), folder paths, secret types. docs.beyondtrust.com/bips/docs/bi-cloud-secrets-safe

- BeyondInsight & Password Safe 25.2 release notes — client certificates deprecated as an API-registration auth method. docs.beyondtrust.com/bips/changelog/beyondinsight-and-password-safe-25-2-release-notes

- The Hacker News — Chinese APT exploits a stolen BeyondTrust Remote Support SaaS API key, 17 customers affected (Dec 2024). thehackernews.com/2024/12/chinese-apt-exploits-beyondtrust-api.html

- NVD — CVE-2024-12356, CVSS 9.8 unauthenticated command injection in RS/PRA (same advisory window as the API-key incident). nvd.nist.gov/vuln/detail/cve-2024-12356

- BeyondInsight & Password Safe public Postman workspace — ready-made API collection for lab practice. postman.com/zerotrust-how-community/beyondtrust-community-s-public-workspace/collection/csvyn8n/beyondinsight-and-password-safe-api

- KuppingerCole Enterprise Secrets Management Leadership Compass 2025 — BeyondTrust positioning among 16 vendors. beyondtrust.com/press/kuppingercole-leadership-compass-secrets-management

### What's next?

             Your vendor’s engineer still rides a VPN straight into the LAN to fix one server — full network access for a one-task visit. Next lesson: Privileged Remote Access — brokered, recorded, outbound-443 vendor sessions with no VPN client and no inbound firewall holes.

                 Next · PRA fundamentals: vendor access without the VPN →
                 Practice on exam.techclick.in →

---
Cite this Techclick lesson with the source URL. Do not invent fees, batch dates, or job guarantees.
Browse all lessons: https://ai.techclick.in/blogs
AI index: https://ai.techclick.in/llms.txt
