diff --git a/server/build.sh b/server/build.sh new file mode 100755 index 0000000..449697d --- /dev/null +++ b/server/build.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +echo "Building..." +cd src/ || exit 1 +go build -o ../ +cd .. +echo "Done." diff --git a/server/cert/cert.pem b/server/cert/cert.pem new file mode 100644 index 0000000..79f19a0 --- /dev/null +++ b/server/cert/cert.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIFCTCCAvGgAwIBAgIUfKEEZwKU9u9YgeHe6hkJTis6UQwwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MDUxNTA2NDg0OFoXDTI2MDUx +NTA2NDg0OFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAxWiPe1gQn8ac1DZR/jvzFxMcCq4Wyh0mNWaI0Yi57tiE +4ZpaTVhUGYmcN7woDjIJH/db1MeeCtWPZQswVfH3XK2p3UAU+eVie4C/ydAktG4R +EhfDjixVDhcGfQ0aAMPod4/Qeelk0ffAW2oUCltGKfm+pHR3fbFbtPTtI1r1bA9n +GDIMMIAwzEklkw96VZiZzJGWTV3KTyDZ0an6fWftFixiy99oqyrD60YP7uuVpbnu +A1sUzOiPL3ZiMd9KXZ3I6wMnI9EUc4Z4Rm4sd3KdEWcCalZsd8JJOM4r8mnSImJe +7VWLFlJz/dmbY0AYqkhF/e/NlHQx9SoardLLeykuOvs2M5V/uwOlQpanv4A8HzPK +cGysNvz5C7L1hkwyGdYQ83IJK2PvV4kR28+e0Z7tqdnR19tuKd47FLbKq3DB1vni +zPzBeJteyC4Z/l3su8x1NJL9vNe4xVycywk2dq7oZKxse4jP9N0VBKoSUGn+1vVn +L6UvYlnZJpDvZ2TXSpCQd8Ru9nbQu3k5kG8fCfwK5EAWQ/k6hRJKoDBpEaYe5ENa +qYF02s04zGRNAPvDlljbninJn9we0f9gTHbo3u5RELqI9M7FKEO78Wl3qnst4YKa +icmp4U9f3JrhR4NM5HGSQ65phwGK1kC7VNUxItV2vV0YFWLnIqnwX09esKJJXAEC +AwEAAaNTMFEwHQYDVR0OBBYEFDYoFgMXo/MEmTf/QK8FBEoYsafzMB8GA1UdIwQY +MBaAFDYoFgMXo/MEmTf/QK8FBEoYsafzMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI +hvcNAQELBQADggIBACnhI7xTPTGoL0adHQtdicYO7UdgMBcpVPTdoFigFwhq+cxz +2Jk/8fJbD6srBW9iiNFET4vOYtjCxOpAuMJkEBl+dWIBZOa2QaRjgiguXNZe4yu1 +egTbUTr8qgB5oU+kMXYLuHIe+QAJ8Yz4XdGa0kYm/K8YSF6C9n7z8dk9I0In789z +VFUP6HTuYS6q0LmstJ/op4J549FZm3IF5bwZTnYTAcWKyk6Gx9nofWtYhfOGnB7E +m7K3qDUcPRdU8hmTDLdPCh07BTVpPbLyzgCslahQiMQuFVOBNh0xtgwjYt60wo6n +lvgi5MOQty+unLX28Hn7NnMawEkAhoQMLGjidTNsHGvtxRLTVwXjWJH2cQ5L/Vch +apu72JJjkFofsDV+lE9U93YWwULzodVW7hAlx0gfop834PJmmX/IwCNvrF69+qMh +EsU/dHgyI6Rt3Xa8SYu/yoEsNMIX1EAFFrh9W3BUr12GSIyYoJdamIWUshDiGz4J +JTYHNNfswEa4QwcXMAS+ZHAXQxZxz995IOYZlAdpSJlCVz5vXvgaykEDo7g3KuDO +E3RazsW9iPhlUskgnmFFxVQW4AxGTplFzMcNQoMXhs/LjnLb2zkeDyW2o9H9I8Ow +GNUA5CXEGfrTcpt5ujRvH/x34GEN2NfPLPweDTVrgJLA2xuXMfWYauKg2vhV +-----END CERTIFICATE----- diff --git a/server/cert/key.pem b/server/cert/key.pem new file mode 100644 index 0000000..e091868 --- /dev/null +++ b/server/cert/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +bqf33hxozZ2xpA+19JwXMvyAiEtbiDM= +-----END PRIVATE KEY----- diff --git a/server/conf/ghostserver.conf b/server/conf/ghostserver.conf new file mode 100644 index 0000000..30097b9 --- /dev/null +++ b/server/conf/ghostserver.conf @@ -0,0 +1,8 @@ +[ghostserver] +address = 0.0.0.0:19070 + +secure = true +certfile = ./cert/cert.pem +keyfile = ./cert/key.pem + +interval = 600 diff --git a/server/ghostrunner-server b/server/ghostrunner-server new file mode 100755 index 0000000..64d14c4 Binary files /dev/null and b/server/ghostrunner-server differ diff --git a/server/src/go.mod b/server/src/go.mod index 10b8cc7..340be3b 100644 --- a/server/src/go.mod +++ b/server/src/go.mod @@ -2,4 +2,9 @@ module ghostrunner-server go 1.24.3 -require github.com/gorilla/mux v1.8.1 +require ( + github.com/gorilla/mux v1.8.1 + gopkg.in/ini.v1 v1.67.0 +) + +require github.com/stretchr/testify v1.10.0 // indirect diff --git a/server/src/go.sum b/server/src/go.sum index 7128337..c55e3e3 100644 --- a/server/src/go.sum +++ b/server/src/go.sum @@ -1,2 +1,12 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/server/src/main.go b/server/src/main.go index 7905807..e8d5b3a 100644 --- a/server/src/main.go +++ b/server/src/main.go @@ -1,5 +1,20 @@ package main -func main() { +import ( + "flag" + "fmt" + "ghostrunner-server/modules/confread" + "ghostrunner-server/modules/restapi" + "log" +) +func main() { + // Begin by trying to find the configuration file. + confPtr := flag.String("conf", "./conf/ghostserver.conf", "Specify a config file location yourself. Relative to the program.") + config := confread.ReadConf(*confPtr) + + log.Println("Starting the API-Server backend.") + restapi.InitApiServer(config) + + fmt.Scanln() } diff --git a/server/src/modules/confread/confread.go b/server/src/modules/confread/confread.go new file mode 100644 index 0000000..597d43d --- /dev/null +++ b/server/src/modules/confread/confread.go @@ -0,0 +1,34 @@ +package confread + +import ( + "ghostrunner-server/modules/utilities" + + "gopkg.in/ini.v1" +) + +const ( + configSection = "ghostserver" +) + +func ReadConf(configPath string) ConfigStruct { + inidata, err := ini.Load(configPath) + utilities.HandleError(err, "Trying to load the ini config file!") + + section := inidata.Section(configSection) + + var config ConfigStruct + + config.Address = section.Key("address").String() + utilities.HandleError(err, "Trying to parse apiport field into the struct!") + + config.Secure, err = section.Key("secure").Bool() + utilities.HandleError(err, "Trying to parse https field into the struct!") + + config.CertFile = section.Key("certfile").String() + config.KeyFile = section.Key("keyfile").String() + + config.Interval, err = section.Key("interval").Int() + utilities.HandleError(err, "Trying to parse interval field into the struct!") + + return config +} diff --git a/server/src/modules/confread/structs.go b/server/src/modules/confread/structs.go new file mode 100644 index 0000000..5298f03 --- /dev/null +++ b/server/src/modules/confread/structs.go @@ -0,0 +1,9 @@ +package confread + +type ConfigStruct struct { + Address string + Secure bool + CertFile string + KeyFile string + Interval int +} diff --git a/server/src/modules/database/init.go b/server/src/modules/database/init.go new file mode 100644 index 0000000..317952e --- /dev/null +++ b/server/src/modules/database/init.go @@ -0,0 +1,5 @@ +package database + +func InitSqlite() { + +} diff --git a/server/src/modules/restapi/handlers.go b/server/src/modules/restapi/handlers.go index e69de29..63f2801 100644 --- a/server/src/modules/restapi/handlers.go +++ b/server/src/modules/restapi/handlers.go @@ -0,0 +1,14 @@ +package restapi + +import ( + "ghostrunner-server/modules/utilities" + "net/http" + + "github.com/gorilla/mux" +) + +func handleSchedule(w http.ResponseWriter, r *http.Request) { + action := mux.Vars(r)["action"] + + utilities.ConsoleLog("Funky Funky " + action) +} diff --git a/server/src/modules/restapi/init.go b/server/src/modules/restapi/init.go index f9381b2..4a8a641 100644 --- a/server/src/modules/restapi/init.go +++ b/server/src/modules/restapi/init.go @@ -1,46 +1,61 @@ package restapi import ( - "crypto/tls" "encoding/json" - "log" + "ghostrunner-server/modules/confread" + "ghostrunner-server/modules/utilities" "net/http" + "time" "github.com/gorilla/mux" ) const ( - defaultMessage = "GhostRunner Server, HTTP REST API. Version: 0.0.1." + defaultMessage = "GhostRunner Server, HTTP REST API. Version: 0.0.1." + readWriteTimeout = 30 * time.Second //Seconds ) -func rootEndpointHandler(w http.ResponseWriter, r *http.Request) { +func rootEndpointHandler(w http.ResponseWriter, r *http.Request) { // This endpoint handles has been placed in the init section because its basic. w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - log.Println("ROOT HIT") //Comment out later, for debugging purposes + utilities.ConsoleLog("ROOT HIT") //Comment out later, for debugging purposes json.NewEncoder(w).Encode(infoResponse{ Status: http.StatusOK, Message: defaultMessage, }) } -func _initApiServer(secureServer bool, apiKey, apiCert, apiPort string) { - apiRouter := mux.NewRouter().StrictSlash(true) // Initialize the HTTP REST API Router. +func InitApiServer(cfg confread.ConfigStruct) { + rtr := createRouter() + srv := createServer(cfg, rtr) - apiRouter.HandleFunc("/", rootEndpointHandler).Methods("GET") - - if secureServer { // If a secured server is wanted. Use the specified certificate files. - httpServer := &http.Server{ - Addr: apiPort, // Specify the desired HTTPS port. - Handler: apiRouter, // Specify the above created handler. - TLSConfig: &tls.Config{ - Certificates: []tls.Certificate{ // Load the certificate and private key. - loadTLSCertificate(apiCert, apiKey), - }, - }, + go func() { + var err error + if cfg.Secure { + err = srv.ListenAndServeTLS(cfg.CertFile, cfg.KeyFile) + } else { + err = srv.ListenAndServe() } - go httpServer.ListenAndServeTLS("", "") - } else { - go http.ListenAndServe(":"+apiPort, apiRouter) // Transform string slightly to make the expected format. + utilities.HandleError(err, "Initializing the HTTP REST API!") + }() + utilities.ConsoleLog("Successfully started the GhostServer goroutine.") +} + +func createRouter() *mux.Router { + r := mux.NewRouter().StrictSlash(true) + + r.HandleFunc("/", rootEndpointHandler).Methods("GET") + r.HandleFunc("/schedule/{action:register|deregister}", handleSchedule).Methods("POST") + + return r +} + +func createServer(cfg confread.ConfigStruct, ghostHandler http.Handler) *http.Server { + return &http.Server{ + Addr: cfg.Address, // Specify the desired HTTPS port. + Handler: ghostHandler, // Specify the above created handler. + ReadTimeout: readWriteTimeout, + WriteTimeout: readWriteTimeout, } } diff --git a/server/src/modules/restapi/utilities.go b/server/src/modules/restapi/utilities.go deleted file mode 100644 index a5bd490..0000000 --- a/server/src/modules/restapi/utilities.go +++ /dev/null @@ -1,14 +0,0 @@ -package restapi - -import ( - "crypto/tls" - "log" -) - -func loadTLSCertificate(certFile, keyFile string) tls.Certificate { - cert, err := tls.LoadX509KeyPair(certFile, keyFile) - if err != nil { - log.Fatal(err) - } - return cert -} diff --git a/server/src/modules/utilities/utilities.go b/server/src/modules/utilities/utilities.go new file mode 100644 index 0000000..414705e --- /dev/null +++ b/server/src/modules/utilities/utilities.go @@ -0,0 +1,24 @@ +package utilities + +import ( + "crypto/tls" + "log" +) + +func HandleError(err error, task string) { + if err != nil { + log.Fatal("The program crashed unexpectedly while doing: "+task+"\nThe following exception occured:", err) + } +} + +func ConsoleLog(message string) { + log.Println(message) +} + +func LoadCertificate(certFile, keyFile string) tls.Certificate { + cert, err := tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + log.Fatal(err) + } + return cert +}