istio / istio

Connect, secure, control, and observe services.
https://istio.io
Apache License 2.0
35.79k stars 7.72k forks source link

Can istio be used for RequestAuthentication for web sockets? #52950

Open jisaacks opened 1 month ago

jisaacks commented 1 month ago

Describe the feature request

I am using istio for request authentication.

The problem is, my server also supports web socket connections as graphql subscriptions (via apollo)

This is the general flow at the network level.

  1. an HTTP GET request is made to /graphql requesting an upgrade to use websockets. This request does not include any auth.
  2. If the request is upgraded to websockets, an inital websocket message is sent from the client with the data including the auth details that looks like:
    {
    type: 'connection_init',
    payload: {
     'Access-Token': '...'
    }
    }
  3. After the initial connection message is sent, a follow up message is then sent from the client with the subscription details in the message data:
    {
    id: '...',
    type: 'subscribe',
    payload: {
    query: '<graphql-query>'
    }
    }
  4. messages are now sent back to the client

I think to make istio able to authorize this, we would need a way to specify something like fromSocketMessage and then we would need a way to drill into the message to access the property (similar to fromHeaders) like so:

jwtRules:
  - issuer: "my_issuer"
    jwksUri: "http://some-url/jwks.json"
    fromSocketMessage:
    - path: "payload.Access-Token"
    outputClaimToSocketMessage:
    - path: "payload.X-User-ID"
      claim: "data.user_id"

This would change the payload from:

{
  type: 'connection_init',
  payload: {
     'Access-Token': '...'
  }
}

to:

{
  type: 'connection_init',
  payload: {
     'X-User-ID': '...'
  }
}

Then maybe the AuthorizationPolicy could have support for something like this:

to:
    - operation:
        protocol: "ws"
        socketMessageData:
        - path: "payload.type"
        - value: "connection_init"

Meaning when a websocket message is sent, and the data contains the key payload.type and the value is "connection_init"

I am trying to do this in an agnostic way that could work with any type of web sockets, to authenticate based on the socket payload.

Affected product area (please put an X in all that apply)

[ X] Security

jisaacks commented 3 weeks ago

istio may not be able to intercept web-socket traffic easily. Wonder if it would be reasonable to have the client connected to istio and istio also connected to the main container as a middle man. That way istio receives the web-socket messages, can process them, then forward them to the main service on the second socket.