From 09712199d6f0a31314feae0ca402ff57395410a1 Mon Sep 17 00:00:00 2001 From: Brian Pescatore Date: Tue, 11 Aug 2026 01:01:52 +0000 Subject: [PATCH 1/3] Add GetActivationKeyParameters API and ActivationKey v1/v2 discriminated union - Add GET /providers/{provider}/environments/{environment}/activationKeyParameters - Replace flat ActivationKey with oneOf discriminator (ActivationKeyV1, ActivationKeyV2) - Add ActivationKeyEncryptedPayload schema for decrypted v2 inner contents - Add GetActivationKeyParametersResponse with supportedVersions and encryption - Add EncryptionParameters schema (publicKey, algorithm, keyFormat) - Read-only endpoint only (no POST/DELETE/PATCH) --- connection-coordinator/openapi.yaml | 2 + .../paths/environments.yaml | 25 +++ .../schemas/environment.yaml | 174 ++++++++++++++++-- 3 files changed, 181 insertions(+), 20 deletions(-) diff --git a/connection-coordinator/openapi.yaml b/connection-coordinator/openapi.yaml index 19c2ce1..4fd4852 100644 --- a/connection-coordinator/openapi.yaml +++ b/connection-coordinator/openapi.yaml @@ -16,6 +16,8 @@ paths: $ref: paths/environments.yaml#/OneEnvironment /providers/{provider}/environments/{environment}/ConfirmActivationKey: $ref: paths/environments.yaml#/ConfirmActivationKey + /providers/{provider}/environments/{environment}/activationKeyParameters: + $ref: paths/environments.yaml#/ActivationKeyParameters /providers/{provider}/environments/{environment}/interconnects: $ref: paths/interconnects.yaml#/AllInterconnects /providers/{provider}/environments/{environment}/interconnects/{interconnect}: diff --git a/connection-coordinator/paths/environments.yaml b/connection-coordinator/paths/environments.yaml index 4f6d971..882cdcc 100644 --- a/connection-coordinator/paths/environments.yaml +++ b/connection-coordinator/paths/environments.yaml @@ -84,3 +84,28 @@ ConfirmActivationKey: security: [] tags: - Environments + +ActivationKeyParameters: + get: + description: |- + Returns the activation key parameters for an environment. This includes + the supported activation key versions and encryption details for + constructing version 2 (encrypted) keys. + + Key creators should call this endpoint (or use a recently cached response) + before constructing an activation key destined for this environment. + operationId: GetActivationKeyParameters + parameters: + - $ref: "../parameters/_index.yaml#/parameters/x-request-id" + - $ref: "../parameters/_index.yaml#/parameters/provider" + - $ref: "../parameters/_index.yaml#/parameters/environment" + responses: + default: + content: + application/json: + schema: + $ref: "../schemas/environment.yaml#/GetActivationKeyParametersResponse" + description: Successful operation + security: [] + tags: + - Environments diff --git a/connection-coordinator/schemas/environment.yaml b/connection-coordinator/schemas/environment.yaml index 490f0d0..00bf72e 100644 --- a/connection-coordinator/schemas/environment.yaml +++ b/connection-coordinator/schemas/environment.yaml @@ -205,44 +205,122 @@ ConfirmActivationKeyRequest: ActivationKey: description: |- - Activation Keys contain all information needed by a provider to validate a - activation proposal between two provider. + The decoded activation key structure. The key is always transported as a + base64-encoded JSON string between providers. After decoding, the `version` + field determines which variant applies. - The activation key should be base64 encoded whenever it is exchanged between - providers. This helps prevent accidental corruption of the key when - transferring it between clouds. + All versions share a common envelope containing `version` and + `destinationEnvironmentUri`. The remaining fields differ by version. + type: object + required: + - version + - destinationEnvironmentUri + discriminator: + propertyName: version + mapping: + "1": "#/ActivationKeyV1" + "2": "#/ActivationKeyV2" + oneOf: + - $ref: "#/ActivationKeyV1" + - $ref: "#/ActivationKeyV2" + +ActivationKeyV1: + description: |- + Version 1 activation key. All fields are present in cleartext within the + base64-decoded JSON structure. + type: object + required: + - version + - destinationEnvironmentUri + - sharedConnectionUuid + - connectionSizeMbps + - destinationAccountId properties: version: - description: |- - Required. Version of the ActivationKey itself. The version should - match the API version on the creating service. - format: int32 + description: Activation key version. Must be `1` for this variant. type: integer + format: int32 + enum: [1] destinationEnvironmentUri: description: |- Required. The destination environment URI this activation key is intended for use at. type: string sharedConnectionUuid: - description: Required. The UUID assigned to this connection to be used by - both services. + description: |- + Required. The UUID assigned to this connection to be used by both + services. type: string connectionSizeMbps: - description: Required. Size of the connection to be provisioned in mbps. - format: int32 + description: Required. Size of the connection to be provisioned in Mbps. type: integer + format: int32 destinationAccountId: description: |- Required. User supplied account id/number on the destination CSP. - Receiving service MUST verify that the activation key was provided from an authorized user of this account. + Receiving service MUST verify that the activation key was provided + from an authorized user of this account. type: string + +ActivationKeyV2: + description: |- + Version 2 activation key. Sensitive fields are encrypted using the + destination environment's public key. Only `version` and + `destinationEnvironmentUri` remain in cleartext to enable routing and + key selection for decryption. + type: object required: - - connectionSizeMbps - - destinationAccountId - - destinationEnvironmentUri - - sharedConnectionUuid - - version + - version + - destinationEnvironmentUri + - encryptedContents + properties: + version: + description: Activation key version. Must be `2` for this variant. + type: integer + format: int32 + enum: [2] + destinationEnvironmentUri: + description: |- + Required. The destination environment URI this activation key is + intended for use at. Remains in cleartext so the receiver can + identify which environment (and private key) to use for decryption. + type: string + encryptedContents: + description: |- + Required. Base64-encoded ciphertext containing the encrypted inner + payload. The payload is encrypted using the destination environment's + public key (obtained via GetActivationKeyParameters). After + decryption, the plaintext is a JSON object conforming to + ActivationKeyEncryptedPayload. + type: string + format: byte + +ActivationKeyEncryptedPayload: + description: |- + The plaintext JSON structure contained within the `encryptedContents` field + of a version 2 ActivationKey, after decryption. Contains all sensitive + connection parameters that are not visible in the outer envelope. type: object + required: + - sharedConnectionUuid + - connectionSizeMbps + - destinationAccountId + properties: + sharedConnectionUuid: + description: |- + Required. The UUID assigned to this connection to be used by both + services. + type: string + connectionSizeMbps: + description: Required. Size of the connection to be provisioned in Mbps. + type: integer + format: int32 + destinationAccountId: + description: |- + Required. User supplied account id/number on the destination CSP. + Receiving service MUST verify that the activation key was provided + from an authorized user of this account. + type: string ConfirmActivationKeyResponse: description: |- @@ -254,4 +332,60 @@ ConfirmActivationKeyResponse: keyValid: description: Indicates if the remote CSP believes this key is valid. type: boolean - type: object \ No newline at end of file + type: object + +GetActivationKeyParametersResponse: + description: |- + Response describing the activation key parameters for an environment. + Contains the supported activation key versions and encryption details + (if the environment supports encrypted keys). + type: object + required: + - supportedVersions + properties: + supportedVersions: + description: |- + The activation key versions this environment supports. The key creator + should prefer the highest version number in this list. For example, + `[1, 2]` indicates both plaintext and encrypted keys are accepted, + with version 2 (encrypted) preferred. + type: array + items: + type: integer + format: int32 + encryption: + allOf: + - $ref: "#/EncryptionParameters" + description: |- + Encryption parameters for constructing a version 2 activation key. + Present only when the environment supports version 2 keys. Absence of + this field indicates the environment only supports version 1 (plaintext) + keys. + +EncryptionParameters: + description: |- + Encryption details required to construct a version 2 (encrypted) activation + key. The key creator uses these parameters to encrypt the inner payload + before constructing the activation key. + type: object + required: + - publicKey + - algorithm + - keyFormat + properties: + publicKey: + description: |- + The PEM-encoded public key for encrypting activation key contents + destined for this environment. Rotated weekly; the environment accepts + keys encrypted with any of the 4 most recent public keys. + type: string + algorithm: + description: |- + The asymmetric encryption algorithm to use when encrypting the inner + payload with the provided public key. + type: string + example: "RSA-OAEP-256" + keyFormat: + description: The encoding format of the public key. + type: string + example: "PKCS8" \ No newline at end of file From 256c6b4a80d999b4b3a87a256a0490853896a831 Mon Sep 17 00:00:00 2001 From: Brian Pescatore Date: Tue, 1 Sep 2026 20:37:52 +0000 Subject: [PATCH 2/3] Hoist shared envelope (version, destinationEnvironmentUri) onto ActivationKey base Address review feedback: declare the shared envelope properties on the ActivationKey base alongside oneOf, instead of repeating destinationEnvironmentUri in each variant. oneOf branches merge at the same depth, so V1/V2 still contribute their variant-specific fields. version retains its per-variant enum constraint in each branch for discrimination. Backward compatible with v1 keys. --- .../schemas/environment.yaml | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/connection-coordinator/schemas/environment.yaml b/connection-coordinator/schemas/environment.yaml index 00bf72e..80cc4d5 100644 --- a/connection-coordinator/schemas/environment.yaml +++ b/connection-coordinator/schemas/environment.yaml @@ -210,11 +210,25 @@ ActivationKey: field determines which variant applies. All versions share a common envelope containing `version` and - `destinationEnvironmentUri`. The remaining fields differ by version. + `destinationEnvironmentUri`, declared here. The remaining fields differ by + version and are contributed by the matching `oneOf` variant. type: object required: - version - destinationEnvironmentUri + properties: + version: + description: |- + Required. The activation key version. Determines which variant + (ActivationKeyV1 or ActivationKeyV2) applies. + type: integer + format: int32 + destinationEnvironmentUri: + description: |- + Required. The destination environment URI this activation key is + intended for use at. Always in cleartext so the receiver can identify + which environment (and, for version 2, which private key) to use. + type: string discriminator: propertyName: version mapping: @@ -227,7 +241,9 @@ ActivationKey: ActivationKeyV1: description: |- Version 1 activation key. All fields are present in cleartext within the - base64-decoded JSON structure. + base64-decoded JSON structure. In addition to the shared envelope fields + (`version`, `destinationEnvironmentUri`), this variant carries the + connection parameters directly. type: object required: - version @@ -241,11 +257,6 @@ ActivationKeyV1: type: integer format: int32 enum: [1] - destinationEnvironmentUri: - description: |- - Required. The destination environment URI this activation key is - intended for use at. - type: string sharedConnectionUuid: description: |- Required. The UUID assigned to this connection to be used by both @@ -265,9 +276,9 @@ ActivationKeyV1: ActivationKeyV2: description: |- Version 2 activation key. Sensitive fields are encrypted using the - destination environment's public key. Only `version` and - `destinationEnvironmentUri` remain in cleartext to enable routing and - key selection for decryption. + destination environment's public key. Only the shared envelope fields + (`version`, `destinationEnvironmentUri`) remain in cleartext to enable + routing and key selection for decryption. type: object required: - version @@ -279,12 +290,6 @@ ActivationKeyV2: type: integer format: int32 enum: [2] - destinationEnvironmentUri: - description: |- - Required. The destination environment URI this activation key is - intended for use at. Remains in cleartext so the receiver can - identify which environment (and private key) to use for decryption. - type: string encryptedContents: description: |- Required. Base64-encoded ciphertext containing the encrypted inner From 31e0a5928c87dc9f1cd410393f4f4349a65363b3 Mon Sep 17 00:00:00 2001 From: Brian Pescatore Date: Tue, 1 Sep 2026 20:51:03 +0000 Subject: [PATCH 3/3] EncryptionParameters: add nextRotationAt timestamp, soften rotation wording - Add optional nextRotationAt (UTC date-time) so callers know when to refetch the public key, instead of exposing a rotation-frequency parameter. - Soften publicKey rotation guidance: recommend at least weekly, but cadence is agreed between the two partners per their security needs. --- connection-coordinator/schemas/environment.yaml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/connection-coordinator/schemas/environment.yaml b/connection-coordinator/schemas/environment.yaml index 80cc4d5..4164f07 100644 --- a/connection-coordinator/schemas/environment.yaml +++ b/connection-coordinator/schemas/environment.yaml @@ -381,9 +381,20 @@ EncryptionParameters: publicKey: description: |- The PEM-encoded public key for encrypting activation key contents - destined for this environment. Rotated weekly; the environment accepts + destined for this environment. Providers are recommended to rotate at + least weekly, though the rotation cadence is ultimately agreed between + the two partners based on their security needs. The environment accepts keys encrypted with any of the 4 most recent public keys. type: string + nextRotationAt: + description: |- + The UTC timestamp at which this environment will next rotate its + public/private key pair. Informs the caller when to fetch a fresh + public key; a cached key remains usable until then. Optional -- absent + if the environment does not expose a scheduled rotation time. + type: string + format: date-time + example: "2026-09-08T00:00:00Z" algorithm: description: |- The asymmetric encryption algorithm to use when encrypting the inner