@@ -1396,7 +1396,8 @@ a source cluster and detach on promote; clone-on-read on every path.
13961396## 12. Secrets
13971397
13981398** Driver interface:** ` services/secrets/driver/driver.go `
1399- ** AWS:** Secrets Manager | ** Azure:** Key Vault | ** GCP:** Secret Manager
1399+ ** AWS:** Secrets Manager | ** Azure:** Key Vault | ** GCP:** Secret Manager |
1400+ ** OCI:** Vault
14001401
14011402### Secret Operations
14021403
@@ -1417,6 +1418,134 @@ a source cluster and detach on promote; clone-on-read on every path.
14171418
14181419** Total: 7 operations**
14191420
1421+ ### OCI Vault
1422+
1423+ ** Optional capability:** ` server/oci/vault.Extras ` — OCI keeps secret storage
1424+ and key management in one service, addresses everything by OCID, scopes it to a
1425+ compartment and a vault, and only ever * schedules* a deletion. None of that fits
1426+ the portable seven. Its value types live in ` providers/oci/vault ` .
1427+ ** Provider:** ` providers/oci/vault ` | ** Wire:** ` server/oci/vault `
1428+
1429+ OCI publishes Vault under two API versions and CloudEmu claims both, because one
1430+ HTTP server stands in for every OCI endpoint: ` /20180608 ` carries KMS and secret
1431+ management, ` /20190301 ` the secret-retrieval data plane.
1432+
1433+ #### Vaults (` /20180608 ` )
1434+
1435+ | Operation | Route |
1436+ | -----------| -------|
1437+ | ` CreateVault ` | ` POST /vaults ` |
1438+ | ` ListVaults ` | ` GET /vaults ` |
1439+ | ` GetVault ` | ` GET /vaults/{vaultId} ` |
1440+ | ` UpdateVault ` | ` PUT /vaults/{vaultId} ` |
1441+ | ` ScheduleVaultDeletion ` | ` POST /vaults/{vaultId}/actions/scheduleDeletion ` |
1442+ | ` CancelVaultDeletion ` | ` POST /vaults/{vaultId}/actions/cancelDeletion ` |
1443+ | ` ChangeVaultCompartment ` | ` POST /vaults/{vaultId}/actions/changeCompartment ` |
1444+
1445+ #### Master encryption keys (` /20180608 ` )
1446+
1447+ | Operation | Route |
1448+ | -----------| -------|
1449+ | ` CreateKey ` | ` POST /keys ` |
1450+ | ` ListKeys ` | ` GET /keys ` |
1451+ | ` GetKey ` | ` GET /keys/{keyId} ` |
1452+ | ` UpdateKey ` | ` PUT /keys/{keyId} ` |
1453+ | ` ScheduleKeyDeletion ` | ` POST /keys/{keyId}/actions/scheduleDeletion ` |
1454+ | ` CancelKeyDeletion ` | ` POST /keys/{keyId}/actions/cancelDeletion ` |
1455+ | ` ChangeKeyCompartment ` | ` POST /keys/{keyId}/actions/changeCompartment ` |
1456+ | ` CreateKeyVersion ` | ` POST /keys/{keyId}/keyVersions ` |
1457+ | ` ListKeyVersions ` | ` GET /keys/{keyId}/keyVersions ` |
1458+ | ` GetKeyVersion ` | ` GET /keys/{keyId}/keyVersions/{keyVersionId} ` |
1459+
1460+ The KMS management endpoint is per-vault in real OCI, where the vault is
1461+ addressed by host. CloudEmu serves every vault from one host, so ` /keys ` takes
1462+ ` vaultId ` as a query parameter instead.
1463+
1464+ #### Secrets (` /20180608 ` )
1465+
1466+ | Operation | Route |
1467+ | -----------| -------|
1468+ | ` CreateSecret ` | ` POST /secrets ` |
1469+ | ` ListSecrets ` | ` GET /secrets ` |
1470+ | ` GetSecret ` | ` GET /secrets/{secretId} ` |
1471+ | ` UpdateSecret ` | ` PUT /secrets/{secretId} ` |
1472+ | ` GetSecretByName ` | ` GET /secrets/actions/getByName ` |
1473+ | ` ScheduleSecretDeletion ` | ` POST /secrets/{secretId}/actions/scheduleDeletion ` |
1474+ | ` CancelSecretDeletion ` | ` POST /secrets/{secretId}/actions/cancelDeletion ` |
1475+ | ` ChangeSecretCompartment ` | ` POST /secrets/{secretId}/actions/changeCompartment ` |
1476+ | ` ListSecretVersions ` | ` GET /secrets/{secretId}/versions ` |
1477+ | ` GetSecretVersion ` | ` GET /secrets/{secretId}/versions/{versionNumber} ` |
1478+ | ` ScheduleSecretVersionDeletion ` | ` POST /secrets/{secretId}/versions/{n}/actions/scheduleDeletion ` |
1479+ | ` CancelSecretVersionDeletion ` | ` POST /secrets/{secretId}/versions/{n}/actions/cancelDeletion ` |
1480+
1481+ #### Secret bundles — the retrieval data plane (` /20190301 ` )
1482+
1483+ | Operation | Route |
1484+ | -----------| -------|
1485+ | ` GetSecretBundle ` | ` GET /secretbundles/{secretId} ` |
1486+ | ` ListSecretBundleVersions ` | ` GET /secretbundles/{secretId}/versions ` |
1487+ | ` GetSecretBundleByName ` | ` GET /secretbundles/actions/getByName ` |
1488+
1489+ A bundle read is the only way to get a secret's * value* back; the management
1490+ routes above return metadata only. The version is named by exactly one of
1491+ ` versionNumber ` , ` secretVersionName ` or ` stage ` — more than one is rejected
1492+ rather than silently ranked.
1493+
1494+ ** Total: 32 operations**
1495+
1496+ #### Behavior
1497+
1498+ There is no secret outside a vault, and no secret without a master encryption
1499+ key, so the portable ` CreateSecret ` mints a default vault and AES key on first
1500+ use and puts every portable secret there. Portable * reads* , though, reach every
1501+ vault, so a secret created through the OCI-shaped surface is addressable
1502+ portably too.
1503+
1504+ OCI scopes secret names to the vault, so the same name in two vaults is two
1505+ different secrets and that reach makes a bare name ambiguous. Rather than
1506+ silently picking one, every portable operation that keys by name fails with
1507+ ` InvalidArgument ` naming both vaults, and ` CreateSecret ` refuses to mint a name
1508+ another vault already holds. ` ListSecrets ` is unaffected — it addresses nothing
1509+ by name. With one vault in play, which is all the AWS, Azure and GCP secret
1510+ mocks can have, none of this is observable.
1511+
1512+ The KMS surface and the secret surface report different live states, as real
1513+ OCI does: a key or key version is ` ENABLED ` and never ` ACTIVE ` , while a vault or
1514+ secret is ` ACTIVE ` and never ` ENABLED ` . This matters to consumers —
1515+ ` terraform-provider-oci ` 's ` oci_kms_key ` waits for ` ENABLED ` after a create or
1516+ rotate. ` enableKey ` / ` disableKey ` and the ` ENABLING ` / ` DISABLING ` / ` DISABLED `
1517+ states are not served, so a key's lifecycle here is ` ENABLED ⇄ PENDING_DELETION ` .
1518+
1519+ Deletion is scheduled, never immediate. A vault, key, secret or secret version
1520+ moves to ` PENDING_DELETION ` and stays there — nothing reaps it — until the
1521+ deletion is cancelled. A secret pending deletion releases its name, so the same
1522+ name can be taken again in that vault; cancelling then fails rather than
1523+ producing two live secrets alike. The portable ` DeleteSecret ` schedules at the
1524+ soonest OCI permits, one day out, and the portable operations treat the secret
1525+ as gone from that moment, which is the same soft-delete the AWS Secrets Manager
1526+ mock exposes.
1527+
1528+ Secret versions are numbered, and each carries a stage: ` CURRENT ` , ` PENDING ` ,
1529+ ` PREVIOUS ` , ` LATEST ` or ` DEPRECATED ` . Adding a version stages it, and promoting
1530+ one to ` CURRENT ` — via ` UpdateSecret ` 's ` currentVersionNumber ` — is how OCI
1531+ finishes a rotation staged as ` PENDING ` . The portable version identifier is
1532+ OCI's version number, so a non-numeric one is rejected.
1533+
1534+ Every list route requires ` compartmentId ` except the key-version, secret-version
1535+ and bundle routes, whose parent already names one. All paginate with ` limit ` /
1536+ ` page ` , returning the cursor as ` opc-next-page ` . The mutations real OCI runs
1537+ asynchronously record a work request and stamp ` opc-work-request-id ` ;
1538+ ` changeCompartment ` answers ` 202 ` with nothing else, so a waiter must poll.
1539+
1540+ ` definedTags ` is rejected rather than accepted and dropped, since CloudEmu
1541+ models no tag namespaces — use ` freeformTags ` . ` autoKeyRotationDetails ` ,
1542+ ` externalKeyReference ` and ` desiredState ` are rejected the same way.
1543+
1544+ The KMS crypto endpoint — ` encrypt ` , ` decrypt ` , ` sign ` , ` verify ` , ` exportKey `
1545+ and ` generateDataEncryptionKey ` — is claimed only to answer ` 501 ` naming the
1546+ gap rather than leaving a caller with a bare ` 404 ` . CloudEmu records master
1547+ encryption keys but stores no key material, so there is no ciphertext to invent.
1548+
14201549---
14211550
14221551## 13. Logging
0 commit comments