Preview — pending review
This reference is generated from the platform API contract and is still under review. Operations, fields, and descriptions can change before publication.
Create an IPsec site connection from existing objects
Creates one IPsec site connection by REFERENCING four objects that already exist - a VPN service, an IKE
policy, an IPsec policy, a local endpoint group and a peer endpoint group. Nothing is created implicitly
and nothing is cloned: the same policy or endpoint group may back any number of connections. This is the
one endpoint both the manual flow and the step-by-step wizard use; there is no wizard-only shortcut.
Both endpoint groups are required and peerCidrs does not exist here. neutron-VPNaaS's validator makes
the two models mutually exclusive: because this API always creates subnet-less VPN services, a connection
MUST carry a local endpoint group (type subnet) and a peer endpoint group (type cidr), and must not carry
flat peer CIDRs.
Validation: name non-empty and unique in the scope (409 CONFLICT); vpnServiceId, ikePolicyId,
ipsecPolicyId, localEndpointGroupId and peerEndpointGroupId must each reference an existing, READY object
in the scope (unknown -> 404 NOT_FOUND; not yet provisioned -> 409 CONFLICT, since neutron needs the
provider id); localEndpointGroupId must be of type subnet and peerEndpointGroupId of type cidr (wrong way
round -> 422 VALIDATION_FAILED naming the field, matching neutron's WrongEndpointGroupType); the local
subnet must be attached to the service's router (-> 422); peerAddress must be a valid IPv4 address or a
resolvable FQDN (-> 422); presharedKey at least 8 characters; initiator and dpdAction must be enumerated
values; dpdTimeout must be strictly greater than dpdInterval (neutron's own _check_dpd, -> 422);
mtu must be at least 68 and at most the deployment's configured tenant network MTU - a larger tunnel MTU
than the underlay can carry makes large packets disappear silently rather than fail loudly (-> 422 with
the configured ceiling in the message).
Async & state: Asynchronous; returns 202 with the connection in provisioningState PENDING_CREATE.
neutron drives status PENDING_CREATE -> ACTIVE on a successful negotiation, or DOWN/ERROR; a provider
rejection lands on the record as provisioningState ERROR with statusReason, never as a silently dropped
change. resource.updated SSE frames carry each transition.
Errors: 401; 403; 404 when a referenced object does not exist; 409 duplicate name or a referenced
object not yet provisioned; 422 on any field-level or cross-object validation failure; 500 on backend
failure.
Idempotency/Concurrency: Idempotency-Key is required; a replay returns the original 202. presharedKey
is write-only: accepted once, stored app-encrypted, never echoed in this response or any later read.
bearerTokenAuthorizationBearer <token>An API token (pc_live_…) or a service-account key (sak_live_…), created in Identity & Access Management and sent as Authorization: Bearer <token>. Requests are rate limited per credential and per tenant: every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a refused request gets 429 RATE_LIMITED with Retry-After.
scopeId*stringOpaque ownership+authorization scope resolving to tenant + subscription + project.
Idempotency-Key*stringRequired: this operation creates a new resource asynchronously, so a retry without the key would create a second one. Same key+body within 24h replays the original result; the same key with a different body is 409 CONFLICT. Keys are unique per tenant (the same key in two tenants is two different requests). An API token or service-account (bearer) caller MUST send it -- a request without it is refused with 400 IDEMPOTENCY_KEY_REQUIRED (ErrIdempotencyKeyRequired); reuse the same key on every retry of one logical request. A console session gets one from the edge.
uuidapplication/json- body
Payload for creating an IPsec site connection from objects that already exist. Both endpoint groups are required and there is no peerCidrs field: because this API always creates subnet-less VPN services, neutron's validator requires a local endpoint group (type subnet) and a peer endpoint group (type cidr) and forbids flat peer CIDRs. This is the same endpoint the step-by-step wizard calls; there is no wizard-only shortcut.
name*stringConnection display name; must be unique within the scope.
^[^\p{C}\p{Z}\x{10000}-\x{10FFFF}](?:[^\p{C}\p{Zl}\p{Zp}\x{10000}-\x{10FFFF}]*[^\p{C}\p{Z}\x{10000}-\x{10FFFF}])?$1 <= length <= 255description?stringFree-text description.
length <= 255""vpnServiceId*stringAn existing, provisioned VPN service in this scope.
1 <= lengthikePolicyId*stringAn existing, provisioned IKE policy in this scope; it may already be in use by other connections.
1 <= lengthipsecPolicyId*stringAn existing, provisioned IPsec policy in this scope; it may already be in use by other connections.
1 <= lengthlocalEndpointGroupId*stringAn existing endpoint group of type subnet, all of whose subnets are attached to the service's router. Put every local subnet that should reach this peer in this one group - one connection covering several subnets works, a second connection to the same peer gateway does not.
1 <= lengthpeerEndpointGroupId*stringAn existing endpoint group of type cidr naming the remote network or networks.
1 <= lengthpeerAddress*stringPublic address of the remote VPN gateway - an IPv4 address or a resolvable FQDN.
1 <= lengthinitiator?stringNegotiation initiator mode.
"bi-directional""bi-directional""response-only"dpdAction?stringWhat to do when dead peer detection fires.
"hold""hold""clear""disabled""restart""restart-by-peer"dpdInterval?integerDead-peer-detection probe interval in seconds.
1 <= value30dpdTimeout?integerDead-peer-detection timeout in seconds; must be strictly greater than dpdInterval.
2 <= value120mtu?|Tunnel MTU. Omit to inherit the deployment's configured tenant network MTU, which is the right answer on an underlay that cannot carry 1500; a larger value is rejected. Note this is the MTU of the tunnel, NOT the largest packet that fits inside it: ESP adds its own header, IV, padding and ICV, so the usable payload is smaller. Measured on this deployment with mtu 1400, the largest inner IP packet that crossed the tunnel was 1374 bytes (ping -M do -s 1346); 1375 and above failed. A 1372-byte payload - the largest that fits a plain 1400-MTU tenant network - therefore does NOT fit the tunnel. It fails loudly with a local DF / EMSGSIZE error rather than silently, so path-MTU discovery works, but a workload sized to the tenant MTU must be told to lower its own MTU or clamp MSS.
68 <= valueadminStateUp?booleanWhether the connection starts administratively up.
truepresharedKey*stringShared secret configured identically on both endpoints; at least 8 characters. Write-only - stored app-encrypted and never returned by any read.
password8 <= lengthCreation accepted; returns the new site connection in provisioningState PENDING_CREATE. The pre-shared key is never included.
application/json- response
An IPsec site connection, mirroring neutron-VPNaaS ipsec_site_connections. It REFERENCES the VPN service, the IKE and IPsec policies and the two endpoint groups - it never copies or clones them, which is what lets one policy back many connections. The pre-shared key is write-only and appears in no read.
origin?stringWhere the resource was made -- portal for a create on the console, api for an object made straight against the OpenStack API (CLI, Terraform, the Kubernetes cloud provider) that discovery adopted. Informational; nothing behaves differently. Absent from a backend that predates it, which means portal.
"portal""api""system""imported"id*stringPlatform identifier of the site connection.
name*stringConnection display name, unique within the scope.
^[^\p{C}\p{Z}\x{10000}-\x{10FFFF}](?:[^\p{C}\p{Zl}\p{Zp}\x{10000}-\x{10FFFF}]*[^\p{C}\p{Z}\x{10000}-\x{10FFFF}])?$1 <= length <= 255description*stringFree-text description; empty string when unset.
vpnServiceId*stringThe VPN service this connection terminates on. Immutable after creation (neutron marks it allow_put false).
ikePolicyId*stringThe IKE (Phase 1) policy this connection negotiates with. Immutable after creation.
ipsecPolicyId*stringThe IPsec (Phase 2) policy this connection negotiates with. Immutable after creation.
localEndpointGroupId*stringThe endpoint group (type subnet) naming the local end of the tunnel.
peerEndpointGroupId*stringThe endpoint group (type cidr) naming the remote end of the tunnel.
localId?|Local IKE identity as neutron holds it. READ-ONLY and always neutron's default here - it cannot be set or changed through this API, because neutron-vpnaas writes the pre-shared key into ipsec.secrets keyed on the local/peer ADDRESS pair and never on these identities, so a custom identity authenticates against no key at all ("no shared key found").
peerAddress*stringPublic address of the remote VPN gateway - an IPv4 address or a resolvable FQDN.
peerId*stringRemote IKE identity as neutron holds it. READ-ONLY and always equal to peerAddress here, for the same reason as localId.
initiator*stringNegotiation initiator mode.
"bi-directional""response-only"dpdAction*stringWhat to do when dead peer detection fires.
"hold""clear""disabled""restart""restart-by-peer"dpdInterval*integerDead-peer-detection probe interval in seconds.
1 <= valuedpdTimeout*integerDead-peer-detection timeout in seconds; neutron requires it to be strictly greater than dpdInterval.
2 <= valuemtu*integerMaximum transmission unit for the tunnel. Capped at the deployment's configured tenant network MTU - a tunnel MTU above what the underlay carries makes large packets vanish silently instead of failing loudly. The usable payload INSIDE the tunnel is lower again by the IPsec overhead: measured on this deployment with mtu 1400, the largest inner IP packet that crossed was 1374 bytes (ping -M do -s 1346), so the 1372-byte payload a plain 1400-MTU tenant network allows does not fit. Oversized packets fail with a DF / EMSGSIZE error rather than disappearing.
68 <= valueadminStateUp*booleanAdministrative state; false tears the tunnel down without deleting anything.
status?|nullneutron's own status for the connection, verbatim. Null until the provider has reported one. ACTIVE means the security associations are established - it is not by itself evidence that traffic passes.
statusReason?|The provider's own message from the last failed write or negotiation; null when the last write succeeded.
statusReasonCode?|Machine-readable companion to statusReason: a small, OPEN vocabulary of codes the console can branch on without parsing the human text, deliberately a plain string rather than a closed enum so a code the client does not recognize yet degrades to the generic failure message. Today the only value is cancelled: the resource is in its failure state because its create operation was CANCELLED; a provider object the create had already built may be left in place, and the resource's DELETE removes it. Reported only while the resource is in that failure state; null otherwise.
provisioningState*stringLifecycle state of this platform record.
"PENDING_CREATE""PENDING_UPDATE""PENDING_DELETE""READY""ERROR"providerId?|neutron's UUID for this site connection; null until the worker has created it.
curl -X POST "https://example.com/scopes/string/network/vpn/site-connections" \ -H "Idempotency-Key: 497f6eca-6276-4993-bfeb-53cbbbba6f08" \ -H "Content-Type: application/json" \ -d '{ "name": "string", "vpnServiceId": "string", "ikePolicyId": "string", "ipsecPolicyId": "string", "localEndpointGroupId": "string", "peerEndpointGroupId": "string", "peerAddress": "string", "presharedKey": "pa$$word" }'{ "origin": "portal", "id": "string", "name": "string", "description": "string", "vpnServiceId": "string", "ikePolicyId": "string", "ipsecPolicyId": "string", "localEndpointGroupId": "string", "peerEndpointGroupId": "string", "localId": "string", "peerAddress": "string", "peerId": "string", "initiator": "bi-directional", "dpdAction": "hold", "dpdInterval": 1, "dpdTimeout": 2, "mtu": 68, "adminStateUp": true, "status": "ACTIVE", "statusReason": "string", "statusReasonCode": "string", "provisioningState": "PENDING_CREATE", "providerId": "string"}