Make Golang server secure and socket.io server [duplicate] - go

I'm reading https://www.kaihag.com/https-and-go/ and bought an SSL certificate from Comodo which they emailed me a .zip file. All of the files I have so far look like this
csr.pem
private-key.pem
website.com.crt
website.com.ca-bundle
website.com.zip
The above website wants me to concatenate 3 .pem files which I don't have. Incidentally what is the reason the .pem files need to concatenated? Using the above files which haven't been modified, how can https be set up on a golang webserver?

Use https://golang.org/pkg/net/http/#ListenAndServeTLS
http.HandleFunc("/", handler)
log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
err := http.ListenAndServeTLS(":10443", "full-cert.crt", "private-key.key", nil)
log.Fatal(err)
For Go you need one certificate file (containing one or more certs, starting with yours) and one private key file (containing one private key).
This isn't really a go question, but the intermediate certs are required because computers only store root certs. By concatenating them you put them all in one file so the browser gets all certs - this is a required step otherwise your server will fail on certain devices. Your cert provider will provide instructions for doing this.
https://kb.wisc.edu/page.php?id=18923
To combine the certs you can just use cat (making sure they have a line feed at the end of the file first), something like:
cat example.com.ca-crt example.com.ca-bundle > example.com.crt

You need http.ListenAndServeTLS
package main
import (
// "fmt"
// "io"
"net/http"
"log"
)
func HelloServer(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte("This is an example server.\n"))
// fmt.Fprintf(w, "This is an example server.\n")
// io.WriteString(w, "This is an example server.\n")
}
func main() {
http.HandleFunc("/hello", HelloServer)
err := http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Here’s a snippet: https://gist.github.com/denji/12b3a568f092ab951456

Here is my finding and I would like to share because it took me a few hours as all available installation guides were for Nginx and Apache HTTP configurations, not for the Golang Web Server.
Environments:
SSL certificate from Comodo / Sectigo
Gin-gonic as middleware
Issue:
It was working fine on Chrome/Firefox on Mac but was giving me a CORS error on Windows Firefox. Later, it was found that it was not really a CORS related matter, and I diagnosed my ubuntu server of the SSL validity by using https://www.digicert.com/help. The result was, "The certificate is not signed by a trusted authority (checking against Mozilla's root store)".
Solution:
The solution is to concatenate the following certificates by using a text editor and name it as you'd like. I saved it as "my_domain.txt".
my_domain.ca-bundle (which includes one root and two intermediate certs)
my_domain.crt (the main cert for my domain)
Then run it like this,
router.RunTLS(":"+os.Getenv("PORT"), "../my_domain.txt", "../my_private_key.txt")
Hope it helped!

IF You Using Go language gin library then use this replace r.run
Here
server.pem = Your SSL intermediate Root CA Certificate.
server.key = Your SSL Key File. :8080 = Your Listen port.
r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")

The library https://github.com/adrianosela/sslmgr abstracts away the whole concept of keys and certificates. All you need is for the server to be reachable by the hostname (i.e. your DNS must point yourdomain.com to your-public-ip). You can even disable SSL for local development as follows:
ss, err := sslmgr.NewServer(sslmgr.ServerConfig{
Hostnames: []string{os.Getenv("yourdomain.com")},
Handler: h,
ServeSSLFunc: func() bool {
return strings.ToLower(os.Getenv("PROD")) == "true"
},
})
if err != nil {
log.Fatal(err)
}
ss.ListenAndServe()

Related

Firebase storage emulator ignored by go admin sdk

I'm trying to setup the storage emulator for my firebase project. I am using the Go admin sdk. However it seems to be ignored despite following the documented process.
App initialization:
func App(ctx context.Context) (*firebase.App, error) {
opt := option.WithCredentialsFile("firebase-service-account.json")
config := firebase.Config{
StorageBucket: "<my-project-id>.appspot.com",
}
app, err := firebase.NewApp(ctx, &config, opt)
if err != nil {
return nil, fmt.Errorf("error initializing app: %v", err)
}
return app, nil
}
.env file loaded on startup:
FIRESTORE_EMULATOR_HOST="localhost:8081"
FIREBASE_STORAGE_EMULATOR_HOST="localhost:9199"
GCLOUD_PROJECT="my-project-id"
I also tried manually setting these by running:
export FIREBASE_STORAGE_EMULATOR_HOST="localhost:9199" and export GCLOUD_PROJECT="my-project-id".
However, when when writing to the default bucket, my blob appears in the actual firestore console for storage, not the storage emulator.
I pulled the GCLOUD_PROJECT value from my service account json file, the project_id field specifically. Also confirmed that 9199 is the port that storage is running on.
Besides setting those FIREBASE_STORAGE_EMULATOR_HOST and GCLOUD_PROJECT am I missing something else?
The variable name is STORAGE_EMULATOR_HOST.
See: https://pkg.go.dev/cloud.google.com/go/storage
Firebaser Here,
You're correct in that your current setup should have been sufficient. I've filed an issue in the GO SDK Repo so that this can get addressed.
In the meanwhile the current fix, as #mabg pointed out, is to set the STORAGE_EMULATOR_HOST variable as well Code Sample

Firebase Go wants host "firebaseio.com"

I'm new to firebase and I'm trying to setup a small test with a simple database in Go.
I struggle a lot with the database connection. Here is my code:
tx := context.Background()
conf := &firebase.Config{
DatabaseURL: "https://mydb.europe-west1.firebasedatabase.app",
}
// Fetch the service account key JSON file contents
opt := option.WithCredentialsFile("./fireBasePrivateKey.json")
// Initialize the app with a service account, granting admin privileges
app, err := firebase.NewApp(ctx, conf, opt)
if err != nil {
log.Fatalln("Error initializing app:", err)
}
client, err := app.Database(ctx)
if err != nil {
log.Fatalln("Error initializing database client:", err)
}
With that code (which comes from the official documentation), I've got an error on the Database client initialization:
invalid database url: wants host: .firebaseio.com
I then tried with the requested url: mydb.firebaseio.com -> I've got another error telling me my db is not in that region and gives me the previous db address.
I also tried other things like mydb.europe-west1.firebaseio.com but here it says me the certificate is not valid for this url...
I'm a bit lost. I understand the problem has to do with the localization of the DB I choose when I created it, but I don't understand how to handle it with the go implementation.
The <projectname>.firebaseio.com format used to be the only format for Firebase Database URLs until early last year. Nowadays, databases in the US still use that format, but databases in other regions use the <dbname><region>.firebasedatabase.app format that you have.
Support for the newer URL format was added in PR #423 and released in version 4.6 of the Go Admin SDK, which was released in June. Upgrade to this version (or later), to ensure you don't get the error message anymore.

Webview not rendering page on some Windows systems

I am using github.com/webview/webview to render a web view on a Go app. It works fine on one system where I am writing it. But the request does not make it to the http server on some clean installed systems. It appears the failure is within the webview dlls. But I am at a loss on how to debug it.
Currently using Go 1.17.1 on Windows 10 Pro x64 21H1
I am running very simple code, similar to the example... I am also using go to serve an http page. I am then opening a webview box to interact with it.
On the Windows development machine, everything works as expected.
On a separate clean install of Windows (all same versions), the box comes up blank - just white. Not crashing though. Just not displaying anything.
Hitting the same URL from a browser on the local machine works. So the page works.
Changing the URL to refer to an external site (e.g. http://google.com), it works on all machines
On some machines, it works. Others not.
I have the DLLs in the same folder as the EXEs.
Adding debugging statements, it's mostly executing everything as expected.
However, the request is not making it to the HTTP server
BTW, the code also works fine on Linux...
The only pattern I can see is that the Windows machines that work seem to be older ones that have existed and been updated for some time. Relatively fresh installs seem to fail. So there must be some kind of subtle dependency?
I'm not sure how to debug this. It seems to be failing within the Webview code.
Any suggestions would be most appreciated... Simple test code below...
main.go
package main
import (
"html/template"
"log"
"net/http"
"github.com/gorilla/mux"
"github.com/webview/webview"
)
var (
IPport = "127.0.0.1:8080"
URL = "http://" + IPport
)
func main() {
log.Print("Starting main")
go HTTPServer(IPport)
OpenUI(URL)
}
func OpenUI(url string) {
log.Print("Starting OpenUI")
w := webview.New(true)
defer w.Destroy()
w.SetTitle("Webview Window")
w.SetSize(800, 600, webview.HintFixed)
w.Navigate(url)
w.Run()
}
func HTTPServer(ipPort string) {
log.Print("Starting HTTPserver")
rtr := mux.NewRouter()
rtr.HandleFunc("/", Page)
log.Printf("Listening on %s\n", ipPort)
err := http.ListenAndServe(ipPort, rtr)
if err != nil {
log.Print(err)
}
}
func Page(w http.ResponseWriter, r *http.Request) {
log.Print("Starting Page handler")
var err error
tmpl := template.New("page")
if tmpl, err = tmpl.ParseFiles("page.gohtml"); err != nil {
log.Print(err)
}
if err = tmpl.ExecuteTemplate(w, "page", nil); err != nil {
log.Print(err)
}
}
page.gohtml
{{define "page"}}
<!doctype html>
<html lang="en">
<body>
<h1>Hello Page</h1>
</body>
</html>
{{end}}
Output on working system...
2021/09/21 11:51:00 Starting main
2021/09/21 11:51:00 Starting OpenUI
2021/09/21 11:51:00 Starting HTTPserver
2021/09/21 11:51:00 Listening on 127.0.0.1:8080
2021/09/21 11:51:02 Starting Page handler
Output on failing system... Again, this will work if you hit it with a web browser... e.g. Edge
2021/09/21 11:52:00 Starting main
2021/09/21 11:52:00 Starting OpenUI
2021/09/21 11:52:00 Starting HTTPserver
2021/09/21 11:52:00 Listening on 127.0.0.1:8080
After a couple of days of fiddling... I figure it out.
You need to actually install one of the Webview2 runtimes. It seems on my older Windows systems, the required dependencies were satisfied through some previous updates or other unknown means. I certainly never installed the runtime specifically. But on a fresh install, you need to install one of the runtime options. You still need the dlls in the same folder as the exe. Once installed, it works everywhere.
See:
https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution
Someone should update the README to mention the installation of the runtime... I used the Bootstrapper as it's smaller.
Thanks for listening...

How can i open/serve a file locate on another computer in Go?

I work on an web application written in Go and React. I am deploying that app on Google Cloud Platform, for which I chose the Compute Engine service.
I created 3 instances: an instance for running the Go part of the application, an other for the database server and the last for the React part. The OS of the three instances is Ubuntu 18.04.
I want my Go program to retrieve data from my database (that part works well) and serve them to the client (React) using websocket.
When I test my app locally, everything runs as expected but it's because html/css/js files are on the same computer that my Go files. But on GCE they are on two differents VMs. Actually this is how I serve a html file with Go:
indexFile, err := os.Open("views/index.html")
if err != nil {
fmt.Println(err)
}
index, err := ioutil.ReadAll(indexFile)
if err != nil {
fmt.Println(err)
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, string(index))
})
http.ListenAndServe(":8080", nil)
Does someone knows how I can make my app work with Go code on a VM and html/css/js on an other ?
Thanks :)

How to set up HTTPS on golang web server?

I'm reading https://www.kaihag.com/https-and-go/ and bought an SSL certificate from Comodo which they emailed me a .zip file. All of the files I have so far look like this
csr.pem
private-key.pem
website.com.crt
website.com.ca-bundle
website.com.zip
The above website wants me to concatenate 3 .pem files which I don't have. Incidentally what is the reason the .pem files need to concatenated? Using the above files which haven't been modified, how can https be set up on a golang webserver?
Use https://golang.org/pkg/net/http/#ListenAndServeTLS
http.HandleFunc("/", handler)
log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
err := http.ListenAndServeTLS(":10443", "full-cert.crt", "private-key.key", nil)
log.Fatal(err)
For Go you need one certificate file (containing one or more certs, starting with yours) and one private key file (containing one private key).
This isn't really a go question, but the intermediate certs are required because computers only store root certs. By concatenating them you put them all in one file so the browser gets all certs - this is a required step otherwise your server will fail on certain devices. Your cert provider will provide instructions for doing this.
https://kb.wisc.edu/page.php?id=18923
To combine the certs you can just use cat (making sure they have a line feed at the end of the file first), something like:
cat example.com.ca-crt example.com.ca-bundle > example.com.crt
You need http.ListenAndServeTLS
package main
import (
// "fmt"
// "io"
"net/http"
"log"
)
func HelloServer(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte("This is an example server.\n"))
// fmt.Fprintf(w, "This is an example server.\n")
// io.WriteString(w, "This is an example server.\n")
}
func main() {
http.HandleFunc("/hello", HelloServer)
err := http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Here’s a snippet: https://gist.github.com/denji/12b3a568f092ab951456
Here is my finding and I would like to share because it took me a few hours as all available installation guides were for Nginx and Apache HTTP configurations, not for the Golang Web Server.
Environments:
SSL certificate from Comodo / Sectigo
Gin-gonic as middleware
Issue:
It was working fine on Chrome/Firefox on Mac but was giving me a CORS error on Windows Firefox. Later, it was found that it was not really a CORS related matter, and I diagnosed my ubuntu server of the SSL validity by using https://www.digicert.com/help. The result was, "The certificate is not signed by a trusted authority (checking against Mozilla's root store)".
Solution:
The solution is to concatenate the following certificates by using a text editor and name it as you'd like. I saved it as "my_domain.txt".
my_domain.ca-bundle (which includes one root and two intermediate certs)
my_domain.crt (the main cert for my domain)
Then run it like this,
router.RunTLS(":"+os.Getenv("PORT"), "../my_domain.txt", "../my_private_key.txt")
Hope it helped!
IF You Using Go language gin library then use this replace r.run
Here
server.pem = Your SSL intermediate Root CA Certificate.
server.key = Your SSL Key File. :8080 = Your Listen port.
r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")
The library https://github.com/adrianosela/sslmgr abstracts away the whole concept of keys and certificates. All you need is for the server to be reachable by the hostname (i.e. your DNS must point yourdomain.com to your-public-ip). You can even disable SSL for local development as follows:
ss, err := sslmgr.NewServer(sslmgr.ServerConfig{
Hostnames: []string{os.Getenv("yourdomain.com")},
Handler: h,
ServeSSLFunc: func() bool {
return strings.ToLower(os.Getenv("PROD")) == "true"
},
})
if err != nil {
log.Fatal(err)
}
ss.ListenAndServe()

Resources