Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/itzg/grpc-authenticated-greeter

Trying out authenticated gRPC communication with Go
https://github.com/itzg/grpc-authenticated-greeter

golang grpc grpc-go x509-auth

Last synced: about 1 month ago
JSON representation

Trying out authenticated gRPC communication with Go

Awesome Lists containing this project

README

        

## Building

```shell script
go build
```

## Example usage

Generate CA, server, and client certs
```shell script
./grpc-authenticated-greeter gencerts
```

Start the server on port 7676:
```shell script
./grpc-authenticated-greeter server \
--ca ca_cert.pem --cert server_cert.pem --key server_key.pem \
--binding :7676
```

In another terminal, run a client:
```shell script
./grpc-authenticated-greeter client \
--ca ca_cert.pem --cert client1_cert.pem --key client1_key.pem \
--serveraddress 127.0.0.1:7676 --servername server \
--message "Read me"
```

The client should log the response from the server, such as:
```
INFO[0000] got response response="Hello, client1. You said 'Read me'"
```

## Re-generating protobuf/gRPC code

[Follow these instructions](https://grpc.io/docs/quickstart/go/#install-protocol-buffers-v3) to install protoc and the grpc plugin.

Run the following to regenerate the `*.pb.go` file, [protocol/HelloService.pb.go](protocol/HelloService.pb.go)

```shell script
go generate ./...
```

## What I learned

- [go-arg](https://github.com/alexflint/go-arg) is very cool! Just feed it a struct and it'll parse command line arguments. It's very flexible and intuitive. Even embedding common arguments into a "command struct" did what I expected
```go
type ClientServerArgs struct {
Ca string `arg:"required" help:"PEM file containing the CA cert shared by server and clients"`
Key string `arg:"required" help:"PEM file containing private key"`
Cert string `arg:"required" help:"PEM file containing public certificate"`
}

type ServerCmd struct {
ClientServerArgs
Binding string `arg:"required" help:"host:port of server binding where host is optional"`
}
```
- Generating a self-signed CA cert and then signing client and server certs is quite doable in Go. Check out [certs/generate.go](certs/generate.go) to see how that's done
- The authenticating client info is a little bit buried when implementing a server handler, but [peer.FromContext](https://godoc.org/google.golang.org/grpc/peer#FromContext) was the key to cracking that open. [server/server.go](server/server.go) is where that is used.
- To do full [mTLS authentication](https://grpc.io/docs/guides/auth/), be sure to configure the server's TLS to require and verify the client cert:
```go
transportCreds := credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: clientCertPool,
})
```
- The [Go package can be configured](https://github.com/golang/protobuf#packages-and-input-paths) for the code generated from the protobuf declarations. The following in [protocol/HelloService.proto](protocol/HelloService.proto) avoids the awkwardness of a package named for the proto file:
```proto
option go_package = "protocol";
```