Home > OS >  Can I have insecure GET HTTP requests whilst having MTLS securing all other HTTP requests?
Can I have insecure GET HTTP requests whilst having MTLS securing all other HTTP requests?

Time:10-14

I have a HTTP REST service written in golang demonstrating what I'm attempting.

I want GET requests insecure and all other REST requests secured with MTLS. My implementation already uses the gin web server library so I'd like to stick with that if possible.

My issue is that I have only been able to apply the tlsConfig to both groups or neither. I've been unable to find a way to apply this at the group level.

package main

import (
    "crypto/tls"
    "crypto/x509"
    "errors"
    "fmt"
    "io/ioutil"
    "net/http"

    "log"

    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.Default()

    // Unprotected public router for GET requests
    public := router.Group("/")

    // Private router with MTLS
    private := router.Group("/")

    public.GET("/insecure-ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "insecure pong",
        })
    })

    private.POST("/secure-ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "secure pong",
        })
    })

    // Get the SystemCertPool, continue with an empty pool on error
    rootCAs, err := x509.SystemCertPool()
    if err != nil {
        log.Fatal(err)
    }
    if rootCAs == nil {
        rootCAs = x509.NewCertPool()
    }

    // Create a CA certificate pool and add cacert.pem to it
    caCert, err := ioutil.ReadFile("cacert.pem")
    if err != nil {
        log.Fatal(err)
    }

    if ok := rootCAs.AppendCertsFromPEM(caCert); !ok {
        err := errors.New("failed to append CA cert to local system certificate pool")
        log.Fatal(err)
    }

    server := http.Server{
        Addr:    fmt.Sprintf(":%v", 8080),
        Handler: router,
    }

    server.TLSConfig = &tls.Config{
        RootCAs: rootCAs,
    }

    err = server.ListenAndServeTLS("certificate.crt", "privateKey.key")
    if err != nil {
        log.Fatal(err)
    }
}

CodePudding user response:

Just create two Server instances and run them both, one with ListenAndServe and one with ListenAndServeTLS, configured with the same routes. Because HTTP and HTTPS operate on different ports, they have to have different listeners, but both listeners can use the same (or different) handlers. For example:

publicRouter := gin.Default()

// Unprotected public router for GET requests
public := publicRouter.Group("/")

public.GET("/insecure-ping", func(c *gin.Context) {
    c.JSON(200, gin.H{
        "message": "insecure pong",
    })
})

server := http.Server{
    Addr:    fmt.Sprintf(":%v", 8081), // Or whatever
    Handler: publicRouter,
}

go func() {
    err = tlsServer.ListenAndServe()
    if err != nil {
        log.Fatal(err)
    }
}()

// Private router with MTLS
router := gin.Default()
private := router.Group("/")

private.POST("/secure-ping", func(c *gin.Context) {
    c.JSON(200, gin.H{
        "message": "secure pong",
    })
})

// Get the SystemCertPool, continue with an empty pool on error
rootCAs, err := x509.SystemCertPool()
if err != nil {
    log.Fatal(err)
}
if rootCAs == nil {
    rootCAs = x509.NewCertPool()
}

// Create a CA certificate pool and add cacert.pem to it
caCert, err := ioutil.ReadFile("cacert.pem")
if err != nil {
    log.Fatal(err)
}

if ok := rootCAs.AppendCertsFromPEM(caCert); !ok {
    err := errors.New("failed to append CA cert to local system certificate pool")
    log.Fatal(err)
}

tlsServer := http.Server{
    Addr:    fmt.Sprintf(":%v", 8080),
    Handler: router,
}

tlsServer.TLSConfig = &tls.Config{
    RootCAs: rootCAs,
}

err = tlsServer.ListenAndServeTLS("certificate.crt", "privateKey.key")
if err != nil {
    log.Fatal(err)
}
  • Related