-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Specification
In some AgentService handlers we need to be able to verify the connecting node information such as the NodeId, certificates and connection information. Since the ForwardProxy<->ReverseProxy connection uses mTLS to ensure a secure connection we can obtain this trusted information from the ReverseProxy.
We need to copy and adapt the authenticator implementation from the client/utils. it should be called getTrustedConnectionInfo. This needs to fetch the connection info from the ReverseProxy. The ReverseProxy provides the ReverseProxy.getConnectionInfoByProxy() method for fetching this information. The information will take this form.
type ConnectionInfo = {
nodeId: NodeId;
certificates: Array<Certificate>;
egressHost: Host;
egressPort: Port;
ingressHost: Host;
ingressPort: Port;
};Within the handler we can obtain the the host and port of the incoming address by using call.getPeer() This will return the address information in the form of host:port. This can be used to look up the information from the ReverseProxy.
Usage
The fix for this introduced a connectionInformationGetter to the agent service container. This allows you to access it within the service handlers by doing ...
function echo({
connectionInfoGetter,
}: {
connectionInfoGetter: ConnectionInfoGetter;
}) {
return async (
call: grpc.ServerUnaryCall<utilsPB.EchoMessage, utilsPB.EchoMessage>,
callback: grpc.sendUnaryData<utilsPB.EchoMessage>,
): Promise<void> => {
const connectionInfo = connectionInfoGetter(call);
if ( connectionInfo == null) throw new agentErrors.ErrorConnectionInfoMissing();
// ...
};
}If it can't find the respective connectionInfo connectionInfoGetter will return undefined but during normal operation when connecting through the proxies this should never happen. You can't obtain any information when connecting directly bypassing proxies. this only happens in testing so far.
connectionInfoGetter takes the call as a parameter. It uses call.getPeer() to get the connection info. This should be parsed as a URL to handle it more robustly. The format of call.getPeer() is usually Host:Port but it can be protocol://Host:Port.
When using connectionInfoGetter we need an error for when we fail to obtain the ConnectionInfo. ErrorConnectionInfoMissing error needs to be created for this. Likely use the sysexits.UNAVAILABLE exit code in this case.
Additional context
- Relevant discussion found from comments Redesign usage of CDSS with
VaultInternal#305 (comment) to Redesign usage of CDSS withVaultInternal#305 (comment). - Session Bin Test Fixes #296 (comment)
- Related Introducing vault sharing and the restrictions of pulling and cloning with vault permissions #266
- Blocking Redesign usage of CDSS with
VaultInternal#305
Tasks
- 1. create a
getTrustedConnectionInfoutility that mimics the use ofauthenticatorinclient/utils.- It needs to take in the call directly as a parameter.
- It needs to handle the peer information as a URL
- when used if the connectionInfo is required by the handler. It should throw an
ErrorConnectionInfoMissingerror. - It needs to fetch and return the connections trusted
ConnectionInfofromReverseProxy.getConnectionInfoByProxy() - It needs to be provided to the service handlers via the
createService(container)parameter similar to how the clientauthenticatorworks
- 2. testing
- We can obtain the connection information
- Add test for multiple connections at a time to check if the proxy information is different for each.