vmagamedov/grpclib

How to add Channel Credentials?

maitham opened this issue · 3 comments

I currently have the following code:

composite_credentials = grpc.composite_channel_credentials(
            ssl_credentials, google_auth_credentials
        )
Channel(host, port, ssl=composite_credentials, loop=loop)

This doesn't work as this returns a composite ChannelCredentials object as per https://www.grpc.io/docs/guides/auth/ . Is this currently supported? Or should I try to get the headers required for authenticating requests to google?

grpclib currently has only basic building blocks to perform authentication. Vendor-specific auth mechanisms (Google) aren't supported because I'm not using these services and I don't know the best way to implement this functionality.

If you want to use certificate-based auth – use ssl option when create Channel:

Channel(..., ssl=custom_ssl_context)

This ssl option can be True or instance of the ssl.SSLContext class. So it is not possible to pass your composite_credentials to this option. I have an example of how to perform mutual TLS auth: examples/mtls/client.py, maybe this will help. And probably I have to add more documentation about TLS authentication.

If you want to use token-based auth – make sure you're using secure connection (Channel(..., ssl=True)), and send auth token with request metadata. There is two ways to send auth token in request metadata:

Can you provide an example of how to authenticate with Google using existing functionality in grpclib I mentioned above? Maybe I can add more helpers into grpclib and/or document this properly with examples.

I'm trying to use the auth token method. However with and without a token I get the following error (<Status.UNIMPLEMENTED: 12>, "Received :status = '404'") .

Proto File - which I have regenerated using the python3 -m grpc_tools.protoc -I. --python_out=. --mypy_out=. --python_grpc_out=. cloud_speech.proto

import asyncio
import grpc
import wave
from grpclib.client import Channel, Stream
from cloud_speech_grpc import SpeechStub
from cloud_speech_pb2 import (
    RecognitionConfig,
    RecognitionAudio,
    RecognizeRequest,
)
from gjwt import get_token


class GoogleGrpcClient():
    def __init__(
        self, loop: asyncio.AbstractEventLoop
    ) -> None:
        self.channel = Channel("speech.googleapis.com",
                               "443", ssl=True, loop=loop)
        fn = ./creds.json"
        err, token = get_token(fn)
        self.token = token

    @property
    def _grpc_stub(self):
        return SpeechStub(self.channel)

    @property
    def grpc_config(self) -> RecognitionConfig:
        return RecognitionConfig(encoding=1,
                                 sample_rate_hertz=16000,
                                 language_code="en-GB"
                                 )

    def grpc_audio(self, audio: bytes) -> RecognitionAudio:
        return RecognitionAudio(content=audio)

    async def recognize(self, audio: bytes) -> str:
        return await self._grpc_stub.Recognize(
            RecognizeRequest(
                config=self.grpc_config,
                audio=self.grpc_audio(audio),
            ),
            metadata={"authorization": "Bearer " + self.token}
        )


async def get_transcription():
    fn = "../trimmed.wav"
    fp = wave.open(fn)
    frames = fp.getnframes()
    data = fp.readframes(frames)
    loop = asyncio.get_event_loop()
    client = GoogleGrpcClient(loop)
    try:
        resp = await client.recognize(data)
        print("RESPONSE", resp)
    except Exception as e:
        print("ERROR", e)

loop = asyncio.get_event_loop()
loop.run_until_complete(get_transcription())

Turns out that Google detects gRPC protocol by reading content-type header:

  • I'm getting :status 404 when I send content-type application/grpc+proto
  • I'm getting proper grpc-status when I send content-type application/grpc

But gRPC protocol says that both variants are valid: https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md

Unfortunately grpclib doesn't allow you to set your custom content-type header value.