This commit is contained in:
Dawid Wysokiński 2023-05-03 07:24:27 +02:00
parent 84040af9a2
commit 0ef6d7f682
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
11 changed files with 190 additions and 21 deletions

5
certs/ca-key.pem Normal file
View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIMaSy7CGp7A69DLcmREodmwU8Z06eJw5KxVMByIkVw+xoAoGCCqGSM49
AwEHoUQDQgAEMlHIUMNtdUeoT2k+s0qGuEKcn5/MxTQsvTHn2UtV6llpKzEJwt8P
Xq9wJgKY92KJIVunncJfWH03Pt46w3rsXQ==
-----END EC PRIVATE KEY-----

11
certs/ca.pem Normal file
View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBnDCCAUGgAwIBAgIINzq1sRDfD4UwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ
bG9jYWxob3N0MB4XDTIzMDUwMzA1MTc1NFoXDTMzMDQzMDA1MjI1NFowFDESMBAG
A1UEAxMJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMlHIUMNt
dUeoT2k+s0qGuEKcn5/MxTQsvTHn2UtV6llpKzEJwt8PXq9wJgKY92KJIVunncJf
WH03Pt46w3rsXaN9MHswDgYDVR0PAQH/BAQDAgGmMB0GA1UdJQQWMBQGCCsGAQUF
BwMBBggrBgEFBQcDAjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQvGKzbHLBJ
gQRkitLTkbuzl8Yd7DAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwCgYIKoZI
zj0EAwIDSQAwRgIhAOVxPVGEjsRZ70QMfNsD2gfjrPguOVZZ6sgzKsVB38BuAiEA
0l2us3+vY1c5TARSVTk6OMmTCJrNYlBjYQP7BbWy6HQ=
-----END CERTIFICATE-----

42
certs/cfssl.json Normal file
View File

@ -0,0 +1,42 @@
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"rootca": {
"usages": [
"signing",
"digital signature",
"key encipherment",
"cert sign",
"crl sign",
"server auth",
"client auth"
],
"ca_constraint": {
"is_ca": true
},
"expiry": "87600h"
},
"server": {
"usages": [
"signing",
"digital signing",
"key encipherment",
"server auth"
],
"expiry": "87600h"
},
"client": {
"usages": [
"signing",
"digital signature",
"key encipherment",
"client auth"
],
"expiry": "87600h"
}
}
}
}

5
certs/client-key.pem Normal file
View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILI/RrEZWQ1sOKQSpISjVjzjfnys4SbD53TKVOjCxgNZoAoGCCqGSM49
AwEHoUQDQgAEZDh+LpU9TmChPAocLxlfgCUwa4TBZnsf/NcwOyo2HupLj4Pha63V
kvbg2DSLFF+Fe4HoSiTWpq4Kwd8dnBxrkA==
-----END EC PRIVATE KEY-----

11
certs/client.pem Normal file
View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBmTCCAUCgAwIBAgIUYF9Sr1vgTtG1L5BBlj6yGrPpI0kwCgYIKoZIzj0EAwIw
FDESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTIzMDUwMzA1MTgwMFoXDTMzMDQzMDA1
MTgwMFowFDESMBAGA1UEAxMJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEZDh+LpU9TmChPAocLxlfgCUwa4TBZnsf/NcwOyo2HupLj4Pha63Vkvbg
2DSLFF+Fe4HoSiTWpq4Kwd8dnBxrkKNwMG4wDgYDVR0PAQH/BAQDAgWgMBMGA1Ud
JQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFAMk3Lo4DM5j
EubUazT8r2BuMjs6MBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATAKBggqhkjO
PQQDAgNHADBEAiAGxGpa2fdAC/2uchVei6AZNJhPTTEhgTVQ9F51kqrjuAIgD6UA
2puaVsOnIzKIUxZFY7zhOgZYU7O7sdNCfZX8ic0=
-----END CERTIFICATE-----

9
certs/csr.json Normal file
View File

@ -0,0 +1,9 @@
{
"hosts": ["localhost", "127.0.0.1"],
"key": {
"algo": "ecdsa",
"size": 256
},
"CN": "localhost",
"names": []
}

10
certs/generate.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
# https://github.com/cloudflare/cfssl
# https://rob-blackbourn.medium.com/how-to-use-cfssl-to-create-self-signed-certificates-d55f76ba5781
cfssl selfsign -config cfssl.json --profile rootca "Root CA" csr.json | cfssljson -bare ca
cfssl genkey csr.json | cfssljson -bare server
cfssl genkey csr.json | cfssljson -bare client
cfssl sign -ca ca.pem -ca-key ca-key.pem -config cfssl.json -profile server server.csr | cfssljson -bare server
cfssl sign -ca ca.pem -ca-key ca-key.pem -config cfssl.json -profile client client.csr | cfssljson -bare client
rm ./*.csr

5
certs/server-key.pem Normal file
View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIBMUH4C8W0a0V4C7TQ0PowlIEPyz/j3AaffAOu6UmHNloAoGCCqGSM49
AwEHoUQDQgAESCljhOQJWwvupZtt2HGPty6XJvuyqf7RpxheHTx5rWmEnLeI7DYK
DhKlIzDeH7Opf4rQrqOECxknfxf355/08A==
-----END EC PRIVATE KEY-----

11
certs/server.pem Normal file
View File

@ -0,0 +1,11 @@
-----BEGIN CERTIFICATE-----
MIIBmjCCAUCgAwIBAgIUfqrcRuTGIZsXgJguUp2R/dw0dzgwCgYIKoZIzj0EAwIw
FDESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTIzMDUwMzA1MTgwMFoXDTMzMDQzMDA1
MTgwMFowFDESMBAGA1UEAxMJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAESCljhOQJWwvupZtt2HGPty6XJvuyqf7RpxheHTx5rWmEnLeI7DYKDhKl
IzDeH7Opf4rQrqOECxknfxf355/08KNwMG4wDgYDVR0PAQH/BAQDAgWgMBMGA1Ud
JQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFJL7liSFyGC6
f85d6ic2cgsqBLJSMBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATAKBggqhkjO
PQQDAgNIADBFAiEAq3vKTlnGRw3EysUyNzAaYATDkspyKFnoQ+ItjGq4ixACICpN
tsAyZ4rKQNy0ZGbbUIncM7MY7S+zDAMz8P1Y9YtT
-----END CERTIFICATE-----

View File

@ -2,6 +2,8 @@ package main
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"flag"
"fmt"
@ -18,7 +20,7 @@ import (
"github.com/google/uuid"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/credentials"
)
const defaultAddress = "localhost:50001"
@ -37,14 +39,7 @@ func main() {
_ = logger.Sync()
}()
example := ""
flag.StringVar(
&example,
"example",
exampleUnary,
fmt.Sprintf("%s or %s (default: %s)", exampleUnary, exampleBidirectional, exampleUnary),
)
flag.Parse()
example := parseExample()
conn, err := newConn()
if err != nil {
@ -70,18 +65,57 @@ func main() {
case exampleBidirectional:
sayHelloBidirectional(ctx, client, logger)
default:
logger.Fatal("example doesn't exist", zap.String("example", example))
logger.Error("example doesn't exist", zap.String("example", example))
}
}
func parseExample() string {
example := ""
flag.StringVar(
&example,
"example",
exampleUnary,
fmt.Sprintf("%s or %s (default: %s)", exampleUnary, exampleBidirectional, exampleUnary),
)
flag.Parse()
return example
}
func newConn() (*grpc.ClientConn, error) {
transport, err := newTransportCredentials()
if err != nil {
return nil, err
}
return grpc.Dial(
"localhost:50001",
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithTransportCredentials(transport),
grpc.WithBlock(),
)
}
func newTransportCredentials() (credentials.TransportCredentials, error) {
cert, err := tls.LoadX509KeyPair("./certs/client.pem", "./certs/client-key.pem")
if err != nil {
return nil, fmt.Errorf("couldn't load client cert: %w", err)
}
data, err := os.ReadFile("./certs/ca.pem")
if err != nil {
return nil, fmt.Errorf("couldn't load CA file: %w", err)
}
capool := x509.NewCertPool()
if !capool.AppendCertsFromPEM(data) {
return nil, errors.New("couldn't add ca cart to cert pool")
}
return credentials.NewTLS(&tls.Config{
Certificates: []tls.Certificate{cert},
RootCAs: capool,
}), nil
}
func sayHello(ctx context.Context, client proto.GreeterClient, logger *zap.Logger) {
reply, err := client.SayHello(ctx, &proto.HelloRequest{Name: uuid.NewString()})
if err != nil {
@ -91,6 +125,7 @@ func sayHello(ctx context.Context, client proto.GreeterClient, logger *zap.Logge
}
func sayHelloBidirectional(ctx context.Context, client proto.GreeterClient, logger *zap.Logger) {
// ctx is used in the 2nd goroutine to close the stream client
//nolint:contextcheck
streamClient, err := client.SayHelloBidirectionalStream(context.Background())
if err != nil {
@ -122,9 +157,7 @@ func sayHelloBidirectional(ctx context.Context, client proto.GreeterClient, logg
defer wg.Done()
ticker := time.NewTicker(time.Second)
defer func() {
ticker.Stop()
}()
defer ticker.Stop()
for {
select {

View File

@ -2,6 +2,8 @@ package main
import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"io"
@ -19,10 +21,11 @@ import (
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/status"
)
const defaultAddress = "localhost:50001"
const defaultAddress = ":50001"
func main() {
logger, err := internal.NewLogger()
@ -54,10 +57,7 @@ func main() {
srv.GracefulStop()
}(srv, logger)
logger.Info(
"listening and serving",
zap.String("address", srv.lis.Addr().String()),
)
logger.Info("listening and serving", zap.String("address", srv.lis.Addr().String()))
if err = srv.Serve(); err != nil {
logger.Fatal("something went wrong while serving", zap.Error(err))
@ -72,6 +72,11 @@ type server struct {
}
func newServer(address string, logger *zap.Logger) (*server, error) {
transport, err := newTransportCredentials()
if err != nil {
return nil, err
}
lis, err := net.Listen("tcp", address)
if err != nil {
return nil, err
@ -80,6 +85,7 @@ func newServer(address string, logger *zap.Logger) (*server, error) {
grpc_zap.ReplaceGrpcLoggerV2(logger)
srv := grpc.NewServer(
grpc.Creds(transport),
grpc.ChainUnaryInterceptor(
grpc_recovery.UnaryServerInterceptor(grpc_recovery.WithRecoveryHandler(createPanicHandler(logger))),
grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
@ -109,6 +115,29 @@ func (s *server) GracefulStop() {
s.grpcSrv.GracefulStop()
}
func newTransportCredentials() (credentials.TransportCredentials, error) {
cert, err := tls.LoadX509KeyPair("./certs/server.pem", "./certs/server-key.pem")
if err != nil {
return nil, fmt.Errorf("couldn't load server cert: %w", err)
}
data, err := os.ReadFile("./certs/ca.pem")
if err != nil {
return nil, fmt.Errorf("couldn't load CA file: %w", err)
}
capool := x509.NewCertPool()
if !capool.AppendCertsFromPEM(data) {
return nil, errors.New("couldn't add ca cart to cert pool")
}
return credentials.NewTLS(&tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{cert},
ClientCAs: capool,
}), nil
}
func createPanicHandler(logger *zap.Logger) grpc_recovery.RecoveryHandlerFunc {
return func(p interface{}) error {
logger.Panic(fmt.Sprintf("%v", p), zap.Stack("stack"))
@ -120,8 +149,6 @@ type greeterServer struct {
proto.UnimplementedGreeterServer
}
var _ proto.GreeterServer = (*greeterServer)(nil)
func (g *greeterServer) SayHello(_ context.Context, r *proto.HelloRequest) (*proto.HelloReply, error) {
return &proto.HelloReply{
Message: buildHelloMsg(r.GetName()),