perimeta adapter¶
Features¶
The perimeta module manages configuration on Metaswitch / Microsoft Perimeta
Session Border Controllers (SBCs) through the device’s HTTPS configuration REST API
(https://<device>/config/V<api_version>/). It exposes the SBC’s configuration tree as Inmanta resources: accounts,
SIP/media adjacencies, signaling and media realm groups, service interfaces, codec lists, TLS settings, routing, IPsec
peers and many more. Each managed resource maps one-to-one onto an API resource, and the handler performs CRUD by
issuing GET/PUT/DELETE against that resource’s URI. Unset/null attributes are left untouched on the device.
The bulk of the model and its Python types are code-generated from an RDF schema of the device’s API (under
schemas/) via the inmanta-perimeta-generator tool. Because the Perimeta API has no “replace whole list” operation
and manages every collection member independently, the module also ships a guard mechanism
(perimeta::guard::ListGuard): a guard owns a collection URI and a set of managed_items, enumerates the collection’s
actual members and prunes any member not present in the model. Resources additionally support a report_only flag that
reports drift as non-compliant instead of mutating the device.
Api configuration¶
Connection is described by two entities:
perimeta::PerimetaDevice — the SBC connection target:
Attribute |
Description |
|---|---|
|
Device IP where the API is reachable |
|
API port (default |
|
API version being configured, e.g. |
|
Inmanta agent name |
|
Whether to verify the SBC’s TLS server certificate (default |
|
Relation to a |
perimeta::PerimetaCredentials — API credentials:
Attribute |
Description |
|---|---|
|
Path to the client certificate (PEM) |
|
Path to the RSA private key (PEM) |
Authentication is mutual TLS plus request signing (no username/password). The handler uses the client certificate and
private key for the mTLS handshake, then signs each request: it builds a token from the HTTP method, URL path, selected
headers and body, signs it with RSA PKCS1v15 / SHA256 and puts the base64 signature in the Authorization header.
:bulb:
client_certificate_pathandprivate_key_pathpoint to files that must be readable by the agent. No config files are read by the module at runtime.
Environment variables¶
The handler reads the following environment variables from the agent process:
Variable |
Default |
Description |
|---|---|---|
|
|
Connect/read timeout in seconds for a single Perimeta API request |
Raise PERIMETA_REQUEST_TIMEOUT when the SBC is slow to answer write requests: a read timeout aborts the deploy of
that resource, since the request may already have been processed by the device and is therefore never replayed.
Usage example¶
The example connects to an SBC over mutual TLS, configures an account with a limit and a SIP adjacency linked to it.
import perimeta
import perimeta::account as account
import perimeta::adjacency as adjacency
import perimeta::sip_message_manipulation as sip_message_manipulation
# Connect to the SBC (mutual TLS + request signing)
device = perimeta::PerimetaDevice(
address="192.0.2.10",
port=443,
agent_name="192.0.2.10",
api_version="5.5.20",
verify=false,
credentials=perimeta::PerimetaCredentials(
client_certificate_path="/path/to/perimeta_sbc.cert",
private_key_path="/path/to/perimeta_sbc.pem",
),
)
# Configure an account with a limit
acct = account::Account(
device=device,
account="ci-myaccount",
account_limits=[
account::AccountLimits(
direction="as-source",
call_appearances=42,
call_appearances_use_default=false,
call_setup_rate_max_sustain="manual",
call_setup_rate_max_sustain_value=43,
call_setup_rate_max_sustain_units="per-second",
),
],
)
# Configure a SIP adjacency linked to that account
adjacency::Sip(
adjacency_name="ci-adjacency",
device=device,
service_address="ci-my-service-address",
description="SIP created by CI",
account=acct,
error_profile=sip_message_manipulation::ErrorProfileUnmanaged(
device=device,
profile_name="ci-default-error-profile",
),
p_charging_vector="ensure-present",
)
Each generated API resource comes as an <X>Identity / <X> (managed) / <X>Unmanaged triplet. Use the
*Unmanaged variant (e.g. ErrorProfileUnmanaged above) to reference an API object the model does not own. To prune
stray members from a collection, use
perimeta::guard::ListGuard(device=device, collection_uri="...", managed_items=[...]).
Main entities¶
Core / hand-written entities:
perimeta::PerimetaDevice— SBC connection target.perimeta::PerimetaCredentials— mTLS client-cert + RSA private-key paths.perimeta::PerimetaApiObject— base for any API resource (_uri,_config,device).perimeta::guard::ListGuard— prunes unmanaged members from a guarded collection.
The remaining entities are generated (hundreds across ~34 sub-modules), including for example:
account::Account(+AccountLimits,account::TrafficGroup) — accounts and their call/traffic limits.adjacency::Sip(+ nested SIP limit/policy/interop entities) — SIP adjacencies.signaling::Signaling— signaling configuration.media_realm_group::MediaRealmGroup— media realm groups.service_interface::ServiceInterface(+Ipv4,Ipv6, …) — service interfaces and IP addressing.address_group::AddressGroup/address_group::IpAddress— address groups and members.call_policy_set::CallPolicySet— call policy sets.
Further sub-modules cover codec_list, custom_codec, qos, routing, tunnel/inbound_tunnel, ipsec_peer,
ip_access_control, interop_profile/interop_defaults, peer_group_sip, TLS settings, certificate stores, SIP
signing/verification services, push notifications, diagnostics and more.