The Terra Azure Relay Listener enables secure bidirectional communication with private resources deployed in a customer subscription using the Azure Relay.
Once the channel is established, the listener forwards HTTP requests to a private endpoint and returns the responses to the caller. The listener also supports WebSockets. The listener establishes a persistent WebSocket connection with the private resource and forwards data bidirectionally to and from the caller and private endpoint.
You need to have java installed.
After that, all other interactions are through gradlew[.bat]
.
To run the unit tests, execute the following from your shell.
./gradlew test
Configuration for the service is documented in the application.yml
file.
By default, any request successfully relayed by this listener (a maximum of once per callWindowInSeconds
) will trigger a request to PATCH ${serviceHost}/api/v2/runtimes/${workspaceId}/${runtimeName}/updateDateAccessed
. To tell the listener to pass a request without sending this PATCH, include the custom HTTP header X-SetDateAccessedInspector-Action=ignore
in the request headers. For example, from a Scala service using Http4s, you could add the following to your Headers()
object:
Header.Raw(CIString("X-SetDateAccessedInspector-Action"), "ignore")
To enable access to a Jupyter Notebooks server instance via Azure Relay using the listener, the following configuration settings are required.
c.NotebookApp.allow_origin = '*'
Note: You could add a specific Azure Relay origin if required.
c.NotebookApp.base_url = '/<HYBRID CONNECTION NAME>/'
Where HYBRID_CONNECTION_NAME is the configured Hybrid Connection name.
c.NotebookApp.websocket_url= 'wss://<AZURE_RELAYED_HOST>>/$hc'
In DSVM, Jupyter server config file lives in /home/azureuser/.jupyter/jupyter_server_config.py. Modify the same variables similar to Jupyter notebooks
e.g
c.ServerApp.allow_origin = '*'
c.ServerApp.base_url = '/qi-2-16/'
c.ServerApp.websocket_url = 'wss://qi-relay.servicebus.windows.net/$hc/qi-2-16'
The listener enables the inspection of the relayed HTTP requests.
HTTP requests could be accepted or rejected after being inspected.
All enabled request inspectors will be executed for each request.
If at least one returns false
the request will be rejected.
An inspector is an implementation of the following interface:
public interface RequestInspector {
public boolean inspectWebSocketUpgradeRequest(
RelayedHttpListenerRequest relayedHttpListenerRequest);
public boolean inspectRelayedHttpRequest(RelayedHttpListenerRequest relayedHttpListenerRequest);
}
-
inspectRelayedHttpRequest
is called before the relayed HTTP request is forwarded to the target. If the implementation returnsfalse
the client will receive a403
response. -
inspectWebSocketUpgradeRequest
is called before the listener accepts the relayed WebSocket connection. If the implementation returnsfalse
, the listener will deny the WebSocket upgrade request. Azure Relay expects a response in less than 30 seconds; if an inspector blocks the requests for longer than that, the client will receive a timeout. -
The implementation must be a named component, e.g.:
@Component(InspectorNameConstants.HEADERS_LOGGER)
public class HeaderLoggerInspector implements RequestInspector {...}
For a new inspector, an entry must be added to:
public enum InspectorType
An inspector can be enabled by adding its name to the requestInspectors
list in the configuration file.
Host
andVia
HTTP headers are not forwarded to the private endpoint.- WebSocket connections must target a specific URI pattern:
- wss://<RELAY_HOST>/$hc/<HYBRID_CONNECTION_NAME>