This project demonstrates how to use Envoy as a proxy with mutual TLS (mTLS) and gRPC health checking for a Go application.
- Go installed.
- Protocol Buffers v3 installed.
- Go plugins for protocol buffers:
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
- Docker to run Envoy.
opensslcommand-line tool.
-
Create Project Structure:
mkdir -p your_project_name/protos cd your_project_name go mod init your_project_name -
Save the Project Files:
- Save the Envoy configuration as
envoy.yaml. - Save the Go application code as
main.go. - Save the protobuf definition as
protos/time.proto.
- Save the Envoy configuration as
-
Generate Certificates: Follow the instructions in the "Certificate Generation Commands" document to create the
certsdirectory and all necessary keys and certificates. -
Generate Go code from Protobuf:
protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ protos/time.proto -
Install Go Dependencies:
go mod tidy
-
Start the Go Application: In one terminal, run the Go server. It will automatically load the certificates from the
certsdirectory.go run main.go
-
Start Envoy: In a second terminal, run Envoy using Docker. Note the new
-vflag to mount thecertsdirectory into the container so Envoy can access them.docker run --rm -it -p 8080:8080 -p 9901:9901 --network="host" \ -v $(pwd)/envoy.yaml:/etc/envoy/envoy.yaml \ -v $(pwd)/certs:/etc/envoy/certs \ envoyproxy/envoy:v1.22.0
To test the mTLS connection, you need a gRPC client that can also present the correct certificates. grpcurl is perfect for this.
-
Install
grpcurl:go install [github.com/fullstorydev/grpcurl/cmd/grpcurl@latest](https://github.com/fullstorydev/grpcurl/cmd/grpcurl@latest)
-
Call the Service with TLS: This command tells
grpcurlto act as a client, presenting theclient.crtand trusting theca.crt.grpcurl \ -cacert certs/ca.crt \ -cert certs/client.crt \ -key certs/client.key \ -d '{}' \ localhost:8080 time.TimeService/StreamTimeYou should see the time streaming successfully. If you try to run it without the certificates, the connection will be rejected by Envoy.
These openssl commands will create a self-signed Certificate Authority (CA) and use it to issue certificates for your Go application (the "server") and Envoy (the "client").
-
Create a directory for the certificates:
mkdir certs cd certs -
Create the Certificate Authority (CA):
- Generate the CA's private key:
openssl genrsa -out ca.key 4096
- Generate the CA's root certificate. You'll be prompted for information; you can accept the defaults.
openssl req -x509 -new -nodes -key ca.key -sha256 -days 1024 -out ca.crt -subj "/CN=my-ca"
- Generate the CA's private key:
-
Create the Server Certificate (for the Go App):
- Generate the server's private key:
openssl genrsa -out server.key 4096
- Create a Certificate Signing Request (CSR) for the server.
openssl req -new -key server.key -out server.csr -subj "/CN=localhost" - Sign the server certificate with your CA:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 500 -sha256
- Generate the server's private key:
-
Create the Client Certificate (for Envoy):
- Generate the client's private key:
openssl genrsa -out client.key 4096
- Create a CSR for the client.
openssl req -new -key client.key -out client.csr -subj "/CN=envoy" - Sign the client certificate with your CA:
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 500 -sha256
- Generate the client's private key:
-
Return to the project root directory:
cd ..
After running these commands, your certs directory should contain ca.crt, server.crt, server.key, client.crt, and client.key, among other files.