Skip to content

Agent service utility to acquire trusted ConnectionInfo from connecting client node #342

@tegefaulkes

Description

@tegefaulkes

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

Tasks

  • 1. create a getTrustedConnectionInfo utility that mimics the use of authenticator in client/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 ErrorConnectionInfoMissing error.
    • It needs to fetch and return the connections trusted ConnectionInfo from ReverseProxy.getConnectionInfoByProxy()
    • It needs to be provided to the service handlers via the createService(container) parameter similar to how the client authenticator works
  • 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.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions