Bridge Relay (Edge)
A Bridge Relay are connections between one or more realms across two Bondy clusters.
Generally speaking an edge router is a router located at a network boundary or on-premises (office, home) that enables an internal network to connect to external networks.
Description
A Bondy Edge router (edge or edge node) is an operational mode that enables Bondy to act as an edge router i.e. it connects to a Bondy remote cluster not as another cluster node but as an edge node, a special mode which allows it to extend the capabilities of Bondy routing to a subset of realms.
Synchronization
Edge connection establishing requires the synchronization of realm state between edge and remote.
Edge will synchronize:
- Realm configuration state
- Realm private keys should not be replicated.
- So we would replicate only the realm's public signing (EC) and encryption (RSA) public keys.
- The realm's prototype (if it is used by the edge's realm)
- We need to copy the realm and its prototype which will have most of the group, source and grant definitions.
- User data
- User passwords should NOT be replicated (only authorized_keys i.e. cryptosign public keys)
- Group data
- Source data
- Grant data
- Realm private keys should not be replicated.
- Realm registry state
- Registrations
- Subscriptions
The api described below is to be able to configure the proper Bondy Edge router.
Types
input_data()
A Bridge Relay object configuration has the following properties:
name
stringREQUIREDIMMUTABLEThe name to be use as unique identifier for the bridge.
enabled
booleanREQUIREDWhether the bridge is enabled.
false
transport
stringREQUIREDIMMUTABLEThe connection transport. The allowed values are: tls
and tcp
.
tls_opts
objectREQUIREDIMMUTABLEClient certificate.
socket_opts
objectREQUIREDIMMUTABLESocket options.
parallelism
integerREQUIREDIMMUTABLEParallelism.
1
restart
stringREQUIREDIMMUTABLEDefines when a terminated bridge must be restarted. The allowed values are: permanent
and transient
.
- A
permanent
bridge is always restarted, even after recovering from a Bondy node crash or when the node is manually stopped and re-started. Bondy persists the configuration of permanent bridges in the database and reads them during startup. - A
transient
bridge is restarted only if it terminated abnormally. In case of a node crash or manually stopped and re-started they will not be restarted.
idle_timeout
integer | infinityREQUIREDIMMUTABLETime in milliseconds that Bondy will allow for a connection with no activity to be kept alive. Bondy will close the connection after this time.
hibernate
stringREQUIREDIMMUTABLEAllowed values: never, idle and always.
connect_timeout
integer | infinityREQUIREDIMMUTABLETCP connection timeout in milliseconds.
network_timeout
integer | infinityREQUIREDIMMUTABLETime in milliseconds that Bondy will wait for a network connected event. When a connection is dropped, Bondy Bridge Relay connection will wait for the host to have at least one non-loopback network interface address to be available before starting a connection retry.
This is mainly to avoid logging failed connection attempts when Bondy knows there is no network interface address available.
reconnect
objectREQUIREDIMMUTABLEEnables or disables the reconnect feature. Once a connection is established but fails due to an unknown error or by the connecting being aborted by the remote with an error that is recoverable, we might want to ask Bondy to retry the connection e.g. when connecting with realm A the remote aborts the connection with reason no_such_realm
, in this case maybe the realm has not yet been provisioned, so we want the connection to retry indefinitely.
ping
objectREQUIREDIMMUTABLErealms
array[object]REQUIREDIMMUTABLEThe list of realm bridging configuration
Procedures
The following wamp api is used to configure and manage the proper Edge:
Name | URI |
---|---|
Add a bridge | bondy.router.bridge.add |
Remove a bridge | bondy.router.bridge.remove |
Start a bridge | bondy.router.bridge.start |
Stop a bridge | bondy.router.bridge.stop |
Retrieve a bridge | bondy.router.bridge.get |
List all bridges | bondy.router.bridge.list |
Check status of a bridge | bondy.router.bridge.status |
Check spec of a bridge | bondy.router.bridge.check_spec |
Add a bridge
bondy.router.bridge.add(input_data()) -> bridge()
Adds a Bridge Relay specification and optionally starts the bridge.
Call
Positional Args
0
objectThe bridge relay configuration data
Keyword Args
autostart
booleanIf true immediately starts the bridge, otherwise the bridge should be started using bondy.router.bridge.start procedure.
Result
Positional Results
0
objectThe bridge relay object.
Keyword Results
None.
Errors
- bondy.error.already_exists: when the provided bridge name already exists.
Example
./wick --url ws://localhost:19080/ws \
--realm com.leapsight.bondy \
call bondy.router.bridge.add \
'{
"name": "edge_test",
"endpoint": "127.0.0.1:18093",
"transport": "tls",
"realms": [
{
"uri": "com.leapsight.test",
"authid": "device1",
"cryptosign": {
"pubkey": "1766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd",
"privkey": "4ffddd896a530ce5ee8c86b83b0d31835490a97a9cd718cb2f09c9fd31c4a7d71766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd"
}
}
],
"reconnect": {"enabled":true},
"ping": {"enabled":true}
}' --kwarg autostart=true | jq
{
"connect_timeout": 5000,
"enabled": false,
"endpoint": "127.0.0.1:18093",
"idle_timeout": 86400000,
"max_frame_size": "infinity",
"name": "edge_test",
"parallelism": 1,
"ping": {
"enabled": true,
"idle_timeout": 20000,
"max_attemps": 2,
"timeout": 10000
},
"realms": [
{
"authid": "device1",
"cryptosign": {
"privkey": "4ffddd896a530ce5ee8c86b83b0d31835490a97a9cd718cb2f09c9fd31c4a7d71766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd",
"pubkey": "1766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd"
},
"procedures": [],
"topics": [],
"uri": "com.leapsight.test"
}
],
"reconnect": {
"backoff_max": 60000,
"backoff_min": 5000,
"backoff_type": "jitter",
"enabled": true,
"max_retries": 100
},
"restart": "transient",
"socket_opts": {
"keepalive": true,
"nodelay": true
},
"tls_opts": {
"verify": "verify_none"
},
"transport": "tls",
"type": "bridge_relay",
"version": "1.0"
}
Remove a bridge
bondy.router.bridge.remove()
Removes the definition of a bridge from the bridge manager.
Returns an error if undefined or if the bridge is running, but no errors if the bridge doesn't exist or it is removed successfully.
Call
Positional Args
0
stringREQUIREDThe name of the bridge.
Keyword Args
None.
Result
Positional Results
None.
Keyword Results
None.
Errors
- bondy.error.running: when the bridge is running.
Example
./wick --url ws://localhost:19080/ws \
--realm com.leapsight.bondy \
call bondy.router.bridge.remove "edge_test"
Start a bridge
bondy.router.bridge.start(name())
Starts a bridge which has already been defined using bondy.router.bridge.add
.
Call
Positional Args
0
stringREQUIREDThe name of the bridge.
Keyword Args
None.
Result
Positional Results
None.
Keyword Results
None.
Errors
- bondy.error.not_found: when the provided bridge name is not found.
- wamp.error.invalid_argument: when there are an invalid number of positional arguments.
- bondy.error.unknown_error:
Examples
Success Call
- Request
./wick --url ws://localhost:19080/ws \
--realm com.leapsight.bondy \
call bondy.router.bridge.start "edge_test"
Stop a bridge
bondy.router.bridge.stop(name())
Stops an existing running bridge.
Returns an error if the bridge is not running or undefined.
Call
Positional Args
0
stringREQUIREDThe name of the bridge.
Keyword Args
None.
Result
Positional Results
None.
Keyword Results
None.
Errors
- bondy.error.not_found: when the provided bridge name is not found or not running.
- wamp.error.invalid_argument: when there are an invalid number of positional arguments.
Examples
Success Call
- Request
./wick --url ws://localhost:19080/ws \
--realm com.leapsight.bondy \
call bondy.router.bridge.stop "edge_test"
Retrieve a bridge
bondy.router.bridge.get(name()) -> bridge()
Retrieves a Bridge Object specification by name
Call
Positional Args
0
stringREQUIREDThe name of the bridge.
Keyword Args
None.
Result
Positional Results
0
objectThe bridge relay object.
Keyword Results
None.
Errors
- bondy.error.not_found: when the provided bridge name is not found.
- wamp.error.invalid_argument: when there are an invalid number of positional arguments.
Examples
Success Call
- Request
./wick --url ws://localhost:19080/ws \
--realm com.leapsight.bondy \
call bondy.router.bridge.get "edge_test" | jq
- Response:
{
"connect_timeout": 5000,
"enabled": false,
"endpoint": "127.0.0.1:18093",
"hibernate": "idle",
"idle_timeout": 86400000,
"max_frame_size": "infinity",
"name": "edge_test",
"network_timeout": 30000,
"parallelism": 1,
"ping": {
"enabled": true,
"idle_timeout": 20000,
"max_attempts": 2,
"timeout": 10000
},
"realms": [
{
"authid": "device1",
"cryptosign": {
"privkey": "4ffddd896a530ce5ee8c86b83b0d31835490a97a9cd718cb2f09c9fd31c4a7d71766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd",
"pubkey": "1766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd"
},
"procedures": [],
"topics": [],
"uri": "com.leapsight.test"
}
],
"reconnect": {
"backoff_max": 60000,
"backoff_min": 5000,
"backoff_type": "jitter",
"enabled": true,
"max_retries": 100
},
"restart": "transient",
"socket_opts": {
"keepalive": true,
"nodelay": true
},
"tls_opts": {
"verify": "verify_none"
},
"transport": "tls",
"type": "bridge_relay",
"version": "1.0"
}
List all bridges
bondy.router.bridge.list() -> [bridge()]
Returns a list of all installed bridges in the system.
Call
Positional Args
None.
Keyword Args
None.
Result
Positional Results
0
array[object]The all bridges you want to retrieve.
Keyword Results
None.
Errors
Examples
Success Call
- Request
./wick --url ws://localhost:19080/ws \
--realm com.leapsight.bondy \
call bondy.router.bridge.list | jq
- Response:
[
{
"connect_timeout": 5000,
"enabled": false,
"endpoint": "127.0.0.1:18093",
"hibernate": "idle",
"idle_timeout": 86400000,
"max_frame_size": "infinity",
"name": "edge_test",
"network_timeout": 30000,
"parallelism": 1,
"ping": {
"enabled": true,
"idle_timeout": 20000,
"max_attempts": 2,
"timeout": 10000
},
"realms": [
{
"authid": "device1",
"cryptosign": {
"privkey": "4ffddd896a530ce5ee8c86b83b0d31835490a97a9cd718cb2f09c9fd31c4a7d71766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd",
"pubkey": "1766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd"
},
"procedures": [],
"topics": [],
"uri": "com.leapsight.test"
}
],
"reconnect": {
"backoff_max": 60000,
"backoff_min": 5000,
"backoff_type": "jitter",
"enabled": true,
"max_retries": 100
},
"restart": "transient",
"socket_opts": {
"keepalive": true,
"nodelay": true
},
"tls_opts": {
"verify": "verify_none"
},
"transport": "tls",
"type": "bridge_relay",
"version": "1.0"
}
]
Check status of a bridge
bondy.router.bridge.status() -> bridgeStatus()
Returns an object where the key is an installed bridge name and the value is the bridge status object.
The status object has the following properties:
- status — The status of the bridge it can be:
not_started
: The bridge was added but never started since the Bondy node startedstopped
: The bridge was stoppedrestarting
: The bridge crashes and the supervisor is restarting itrunning
: The bridge is running
Call
Positional Args
None.
Keyword Args
None.
Result
Positional Results
status
stringREQUIREDIMMUTABLEThe status of the bridge.
Keyword Results
None.
Errors
Examples
Success Call
- Request
./wick --url ws://localhost:19080/ws \
--realm com.leapsight.bondy \
call bondy.router.bridge.status | jq
- Response:
{
"edge_test": {
"status": "not_started"
}
}
Check spec of a bridge
bondy.router.bridge.check_spec(input()) -> bridge()
Checks the validity of a Bridge Relay Object.
Call
Positional Args
0
objectThe bridge relay configuration data
Keyword Args
None.
Result
Positional Results
0
objectThe bridge relay object.
Keyword Results
None.
Errors
- bondy.error.badmap: when the provided data is invalid according to the spec.
Examples
Success Call
- Request
./wick --url ws://localhost:19080/ws \
--realm com.leapsight.bondy \
call bondy.router.bridge.check_spec \
'{
"name": "edge_test",
"endpoint": "127.0.0.1:18093",
"realms": [
{
"uri": "com.leapsight.test",
"authid": "device1",
"cryptosign": {
"pubkey": "1766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd",
"privkey": "4ffddd896a530ce5ee8c86b83b0d31835490a97a9cd718cb2f09c9fd31c4a7d71766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd"
}
}
]
}' | jq
- Response:
{
"connect_timeout": 5000,
"enabled": false,
"endpoint": "127.0.0.1:18093",
"idle_timeout": 86400000,
"max_frame_size": "infinity",
"name": "edge_test",
"parallelism": 1,
"ping": {},
"realms": [
{
"authid": "device1",
"cryptosign": {
"privkey": "4ffddd896a530ce5ee8c86b83b0d31835490a97a9cd718cb2f09c9fd31c4a7d71766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd",
"pubkey": "1766c9e6ec7d7b354fd7a2e4542753a23cae0b901228305621e5b8713299ccdd"
},
"procedures": [],
"topics": [],
"uri": "com.leapsight.test"
}
],
"reconnect": {},
"restart": "transient",
"socket_opts": {
"keepalive": true,
"nodelay": true
},
"tls_opts": {
"verify": "verify_none"
},
"transport": "tcp",
"type": "bridge_relay",
"version": "1.0"
}