use TLS
This commit is contained in:
30
cert.pem
Normal file
30
cert.pem
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
iCNA98wWcCweUk1NpB6eYqTMbI9Qj4cYZ1MS
|
||||||
|
-----END CERTIFICATE-----
|
52
key.pem
Normal file
52
key.pem
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
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
|
||||||
|
YOtHX+6Qh2feqdNVUqFtlMCuk5iZUel9
|
||||||
|
-----END PRIVATE KEY-----
|
51
main.go
51
main.go
@@ -4,9 +4,13 @@ import (
|
|||||||
"ccsecrets/controllers"
|
"ccsecrets/controllers"
|
||||||
"ccsecrets/middlewares"
|
"ccsecrets/middlewares"
|
||||||
"ccsecrets/models"
|
"ccsecrets/models"
|
||||||
|
"ccsecrets/utils"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@@ -26,12 +30,51 @@ func main() {
|
|||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
router.GET("/", func(c *gin.Context) {
|
router.GET("/", func(c *gin.Context) {
|
||||||
//time.Sleep(10 * time.Second)
|
//time.Sleep(10 * time.Second)
|
||||||
c.String(http.StatusOK, "Welcome Gin Server")
|
c.String(http.StatusOK, "Hello World.")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Set some options for TLS
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
|
||||||
|
PreferServerCipherSuites: true,
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
CipherSuites: []uint16{
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
|
||||||
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
||||||
|
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine bind IP
|
||||||
|
bindIP := os.Getenv("BIND_IP")
|
||||||
|
if bindIP == "" {
|
||||||
|
bindIP = utils.GetOutboundIP().String()
|
||||||
|
}
|
||||||
|
// Determine bind port
|
||||||
|
bindPort := os.Getenv("BIND_PORT")
|
||||||
|
if bindPort == "" {
|
||||||
|
bindIP = "8443"
|
||||||
|
}
|
||||||
|
bindAddress := fmt.Sprint(bindIP, ":", bindPort)
|
||||||
|
fmt.Printf("Will listen on address 'https://%s'\n", bindAddress)
|
||||||
|
|
||||||
|
// Generate certificate if required
|
||||||
|
tlsCertFilename := utils.GetFilePath(os.Getenv("TLS_CERT_FILE"))
|
||||||
|
tlsKeyFilename := utils.GetFilePath(os.Getenv("TLS_KEY_FILE"))
|
||||||
|
|
||||||
|
if !(utils.FileExists(tlsCertFilename) && utils.FileExists(tlsKeyFilename)) {
|
||||||
|
fmt.Printf("Specified TLS certificate (%s) or private key (%s) do not exist.\n", tlsCertFilename, tlsKeyFilename)
|
||||||
|
utils.GenerateCerts(tlsCertFilename, tlsKeyFilename)
|
||||||
|
}
|
||||||
|
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
Addr: ":8080",
|
Addr: bindAddress,
|
||||||
Handler: router,
|
Handler: router,
|
||||||
|
TLSConfig: tlsConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register our routes
|
// Register our routes
|
||||||
@@ -52,7 +95,7 @@ func main() {
|
|||||||
// Initializing the server in a goroutine so that
|
// Initializing the server in a goroutine so that
|
||||||
// it won't block the graceful shutdown handling below
|
// it won't block the graceful shutdown handling below
|
||||||
go func() {
|
go func() {
|
||||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
if err := srv.ListenAndServeTLS(tlsCertFilename, tlsKeyFilename); err != nil && err != http.ErrServerClosed {
|
||||||
log.Fatalf("listen: %s\n", err)
|
log.Fatalf("listen: %s\n", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
157
utils/utils.go
157
utils/utils.go
@@ -1,12 +1,22 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math/big"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const rsaBits = 4096
|
||||||
|
|
||||||
func GetFilePath(path string) string {
|
func GetFilePath(path string) string {
|
||||||
// Check for empty filename
|
// Check for empty filename
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
@@ -27,3 +37,150 @@ func GetFilePath(path string) string {
|
|||||||
}
|
}
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get preferred outbound ip of this machine
|
||||||
|
// @see https://stackoverflow.com/questions/23558425/how-do-i-get-the-local-ip-address-in-go
|
||||||
|
func GetOutboundIP() net.IP {
|
||||||
|
conn, err := net.Dial("udp", "8.8.8.8:80")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
||||||
|
|
||||||
|
return localAddr.IP
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if a file exists from https://stackoverflow.com/questions/12518876/how-to-check-if-a-file-exists-in-go
|
||||||
|
func FileExists(filename string) bool {
|
||||||
|
info, err := os.Stat(filename)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !info.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateCerts(tlsCert string, tlsKey string) {
|
||||||
|
// @see https://shaneutt.com/blog/golang-ca-and-signed-cert-go/
|
||||||
|
// @see https://golang.org/src/crypto/tls/generate_cert.go
|
||||||
|
validFrom := ""
|
||||||
|
validFor := 365 * 24 * time.Hour
|
||||||
|
isCA := true
|
||||||
|
|
||||||
|
// Get the hostname
|
||||||
|
hostname, err := os.Hostname()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the directory exists
|
||||||
|
relativePath := filepath.Dir(tlsCert)
|
||||||
|
fmt.Printf("GenerateCerts relative path for file creation is '%s'\n", relativePath)
|
||||||
|
_, err = os.Stat(relativePath)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
log.Printf("Certificate path does not exist, creating %s before generating certificate\n", relativePath)
|
||||||
|
os.MkdirAll(relativePath, os.ModePerm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a private key
|
||||||
|
priv, err := rsa.GenerateKey(rand.Reader, rsaBits)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to generate private key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var notBefore time.Time
|
||||||
|
if len(validFrom) == 0 {
|
||||||
|
notBefore = time.Now()
|
||||||
|
} else {
|
||||||
|
notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to parse creation date: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notAfter := notBefore.Add(validFor)
|
||||||
|
|
||||||
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||||
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to generate serial number: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
template := x509.Certificate{
|
||||||
|
SerialNumber: serialNumber,
|
||||||
|
Subject: pkix.Name{
|
||||||
|
Organization: []string{"DTMS"},
|
||||||
|
},
|
||||||
|
NotBefore: notBefore,
|
||||||
|
NotAfter: notAfter,
|
||||||
|
|
||||||
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
template.DNSNames = append(template.DNSNames, hostname)
|
||||||
|
|
||||||
|
// Add in all the non-local IPs
|
||||||
|
ifaces, err := net.Interfaces()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error enumerating interfaces: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, i := range ifaces {
|
||||||
|
addrs, err := i.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Oops: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, address := range addrs {
|
||||||
|
// check the address type and if it is not a loopback then add it to the list
|
||||||
|
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||||
|
if ipnet.IP.To4() != nil {
|
||||||
|
template.IPAddresses = append(template.IPAddresses, ipnet.IP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isCA {
|
||||||
|
template.IsCA = true
|
||||||
|
template.KeyUsage |= x509.KeyUsageCertSign
|
||||||
|
}
|
||||||
|
|
||||||
|
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to create certificate: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certOut, err := os.Create(tlsCert)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to open %s for writing: %v", tlsCert, err)
|
||||||
|
}
|
||||||
|
if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
|
||||||
|
log.Fatalf("Failed to write data to %s: %v", tlsCert, err)
|
||||||
|
}
|
||||||
|
if err := certOut.Close(); err != nil {
|
||||||
|
log.Fatalf("Error closing %s: %v", tlsCert, err)
|
||||||
|
}
|
||||||
|
log.Printf("wrote %s\n", tlsCert)
|
||||||
|
|
||||||
|
keyOut, err := os.OpenFile(tlsKey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to open %s for writing: %v", tlsKey, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to marshal private key: %v", err)
|
||||||
|
}
|
||||||
|
if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
|
||||||
|
log.Fatalf("Failed to write data to %s: %v", tlsKey, err)
|
||||||
|
}
|
||||||
|
if err := keyOut.Close(); err != nil {
|
||||||
|
log.Fatalf("Error closing %s: %v", tlsKey, err)
|
||||||
|
}
|
||||||
|
log.Printf("wrote %s\n", tlsKey)
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user