Ротуйте секрет
Замініть секретний об'єкт credential під оптимістичним блокуванням і доведіть, що ротація відбулася.
Вендорський ключ витік, протермінувався чи просто зістарився за політикою. Ротація тут — це заміна цілого об'єкта секрету під оптимістичним блокуванням — без часткових merge, без змін статусу.
Мета
Закінчити з тим самим записом credential (той самий id), який несе новий секрет: version інкрементовано, маска змінилася, конфігурація ціла.
Передумови
- Активний credential зі сценарію 02; його
idі поточнаversion.
Кроки
1. Прочитайте поточний стан
Викличте GET /v1/credentials/{id} і збережіть version та masked_credentials для порівняння.
2. Ротуйте
Викличте PATCH /v1/credentials/{id} з повним новим секретним об'єктом і поточною версією:
curl -s -X PATCH "$CREDS_BASE/v1/credentials/$CRED_ID" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{
"credentials": {"api_key": "sk-live-fedcba9876543210"},
"version": 1
}'
r = httpx.patch(f"{CREDS_BASE}/v1/credentials/{cred_id}", headers=headers, json={
"credentials": {"api_key": "sk-live-fedcba9876543210"},
"version": current_version,
})
assert r.status_code == 200
rotated = r.json()
Очікуване 200: version підросла, masked_credentials помітно інші (маска переобчислюється з нового plaintext), is_default і status неторкані. Старий секрет зник — перешифроване сховище тримає лише новий об'єкт.
3. Доведіть, що блокування вас захищає
Повторіть той самий PATCH зі старою версією:
curl -s -X PATCH "$CREDS_BASE/v1/credentials/$CRED_ID" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"credentials": {"api_key": "sk-live-stale-write"}, "version": 1}'
Очікуване 409 з error.code = "CREDENTIAL_VERSION_CONFLICT" — конкурентний редактор не може мовчки перезаписати вашу ротацію. Перечитати, потім повторити — такий контракт.
Ротація ключа організації чи платформи — той самий виклик
Ідентичний PATCH існує на /v1/org-credentials і на внутрішній адмін-площині; різняться лише власність і ґейт.
Перевірено тестом test_s03_rotate_a_secret.