1

I've been looking for a way to switch to https in my Golang server. I thought I found the way already, which involved generating .pem and .key files and passing them as some sort of credentials, but it didn't work. Here's what my current code looks like, I'm also using gRPC btw:

//client side code

package main

import (
    "bytes"
    "encoding/json"
    "flag"
    "fmt"
    "log"
    "sort"
    "strings"

    "github.com/<me>/<repo_name>/cmd/client/handlers"

    "github.com/gin-gonic/gin"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
)

var (
    addr = flag.String("addr", "localhost:50051", "the address to connect to")
)

func main() {
    creds, err := credentials.NewClientTLSFromFile("service.pem", "")

    if err != nil {
        log.Fatalf("could not process the credentials: %v", err)
    }

    flag.Parse()
    conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(creds))

    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }

    defer conn.Close()

    var ginGine = gin.Default()
    StartClient(conn, ginGine)
}

func StartClient(conn *grpc.ClientConn, ginGine *gin.Engine) {

    //some endpoint setup
    handlers.SomethingApiHandler(conn, ginGine)

    // ginGine.RunTLS(":5000", "service.pem", "service.pem")
    ginGine.Run(":5000")
}

//server side code

package main

import (
    "flag"
    "fmt"
    "log"
    "net"

    pb "github.com/<me>/<repo_name>/api/proto/out"
    "github.com/<me>/<repo_name>/cmd/server/handlers"
    "github.com/<me>/<repo_name>/cmd/server/helpers"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
)

func init() {
    helpers.DatabaseConnection()
}

var (
    port = flag.Int("port", 50051, "gRPC server port")
)

func main() {
    creds, err := credentials.NewServerTLSFromFile("service.pem", "service.key")

    if err != nil {
        log.Fatalf("Failed to setup TLS: %v", err)
    }

    flag.Parse()
    lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
    if err != nil {
        log.Fatalf("Failed to listen: %v", err)
    }

    mServ := grpc.NewServer(grpc.Creds(creds))

    fmt.Println("gRPC server running ...")

    //server side endpoint setup

    log.Printf("Server listening at %v", lis.Addr())

    if err := mServ.Serve(lis); err != nil {
        log.Fatalf("failed to serve : %v", err)
    }
}

Using .RunTLS() seemed to have set the client side, which provides the endpoints, to https but it seems like I need to set the server side as well as I got a TLS Handshake error EOF when I called an endpoint using Postman. But I can't find any example for this so I created this question.

UPDATE:

Here's what SomethingAPIHandler looks like:

func NewSomethingClient(cc *grpc.ClientConn) *SomethingClient {
    service := pb.NewSomethingServiceClient(cc)
    return &SomethingClient{service}
}

func SomeApiHandler(cc *grpc.ClientConn, ginGine *gin.Engine) {
    srvClient := NewSomethingClient(cc)

    ginGine.GET("/something/:id", func(ctx *gin.Context) {
        id := ctx.Param("id")

        //auth checking

        res, err := srvClient.service.GetSomething(ctx, &pb.ReadSomethingRequest{Id: id})
        if err != nil {
            ctx.JSON(http.StatusNotFound, gin.H{
                "message": err.Error(),
            })
            return
        }
        ctx.JSON(http.StatusOK, gin.H{
            "something": res.Something,
        })
    })  
}

So I think I'm using gRPC with Gin. I updated the client side code sample above to show the connection of this update to that code.

rminaj
  • 560
  • 6
  • 28
  • The [route guide](https://github.com/grpc/grpc-go/tree/master/examples/route_guide) sample is probably a good place to start (it's unclear whether you need certificate based authentication for clients or not). However I am a bit confused by your use of Gin (`StartClient` does not actually use the gRPC connection it's unclear what you are trying to accomplish). If your question relates to Gin alone then please remove the gRPC code ([**Minimal**, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example)) and tags because its not relevant to your question. – Brits Jul 02 '23 at 19:44
  • @Brits thanks for the info. gRPC was quite relevant as it was the code that "promised" to set my protocol to `https` after having me create some certificates and use them as credentials – rminaj Jul 03 '23 at 00:30
  • @Brits that's interesting, so I just need some flag to turn on tls. But do you know how I can do that for a named build? I'm planning to install the compiled code to a server and let that run indefinitely – rminaj Jul 03 '23 at 00:45
  • The sample I linked to demonstrates how to use gRPC over TLS; Gin is not needed for this. "so I just need some flag to turn on tls" you need to supply a `TransportCredentials` option, as [shown here](https://github.com/grpc/grpc-go/blob/master/examples/route_guide/server/server.go#L238). The demo uses a flag but whether you do that or hardcode TLS to on is up to you. – Brits Jul 03 '23 at 01:39
  • Hmm, so I guess I'm already done as I already have `credentials.NewServerTLSFromFile` on my code. Will test this out. – rminaj Jul 03 '23 at 01:45
  • Based upon your edit you have an HTTP server that calls a gRPC backend. This is fine but the gRPC and HTTP REST API are quite independent (your REST API could be served over HTTPS but fulfil that request via unencrypted gRPC; or they could both be encrypted but with totally different certificate chains). Currently I'm confused about what link you are trying to use TLS on (the `ginGine.RunTLS` has nothing to do with gRPC). – Brits Jul 03 '23 at 01:47
  • Well, I don't know where to put the TLS as well, whichever works in my setup I guess. But even after copying the code from the sample you showed, at least the server side as both my server and client code is already the same as what's on sample, I'm still on `http`. So does that mean I need to put the TLS on `Gin`? It did work previously, but only on the client side. I don't know how to put TLS on the server side – rminaj Jul 03 '23 at 02:15
  • There are two links - *Postman <--http--> Client* (this is where Gin is relevant) and *Client <--gRPC--> Server* (Gin is irrelevant, this is solely gRPC); these are independent connections (neither, one, or both could use TLS). If you want to use TLS from Postman (or browser/whatever) to Client then that is where `ginGine.RunTLS(":5000", "service.pem", "service.pem")` is relevant (and your issue might be that Postman is not configured to trust the CA that issues the certs - [see here](https://learning.postman.com/docs/sending-requests/certificates/#troubleshooting-certificate-errors)). – Brits Jul 03 '23 at 03:11
  • Hmm, I see. Will check this out – rminaj Jul 03 '23 at 03:32

0 Answers0