Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions config/default.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# Configuration file for API Gateway
#

#connections:
# routes:
# - path:
# url:
# rate-limit:
# zone:
# rate:
# auth:
93 changes: 54 additions & 39 deletions dataplane/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,81 +10,96 @@ import (
"path/filepath"
)

type Response struct {
Filename string `json:"filename"`
Body []byte `json:"body"`
type ConfigRequest struct {
Files map[string][]byte `json:"files"`
}

func main() {
mux := http.NewServeMux()

mux.HandleFunc("/api/handle-config", handleNewConfig)
err := http.ListenAndServe(":1000", mux)
if err != nil {

slog.Info("Starting dataplane on :1000")
if err := http.ListenAndServe(":1000", mux); err != nil {
slog.Error("Error starting HTTP server", "error", err)
}
}

func handleNewConfig(w http.ResponseWriter, r *http.Request) {
slog.Info("handling config update")
res := &Response{}

if r.Method != "POST" {
if r.Method != http.MethodPost {
slog.Error("Invalid request method", "method", r.Method)
http.Error(w, "invalid method", http.StatusMethodNotAllowed)
return
}

err := json.NewDecoder(r.Body).Decode(&res)
if err != nil {
var req ConfigRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
slog.Error("Error unmarshalling request body", "error", err)
http.Error(w, "bad request", http.StatusBadRequest)
return
}

dir := filepath.Dir(res.Filename)
err = os.MkdirAll(dir, 0644)
if err != nil {
slog.Error("Error creating directory", "error", err)
return
}

username := filepath.Base(filepath.Dir(res.Filename))
logDir := "/var/log/nginx/users/" + username
err = os.MkdirAll(logDir, 0755)
if err != nil {
slog.Error("Error creating log directory", "error", err)
return
}

file, err := os.Create(res.Filename)
if err != nil {
slog.Error("Error creating file", "filename", res.Filename)
return
for path, content := range req.Files {
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0755); err != nil {
slog.Error("Error creating directory", "dir", dir, "error", err)
continue
}

// Ensure username log dir exists
username := filepath.Base(filepath.Dir(path))
logDir := filepath.Join("/var/log/nginx/users", username)
if err := os.MkdirAll(logDir, 0755); err != nil {
slog.Error("Error creating log directory", "dir", logDir, "error", err)
}

// Atomic write
tmpFile, err := os.CreateTemp(dir, "nginx-*.conf")
if err != nil {
slog.Error("Error creating temp file", "dir", dir, "error", err)
continue
}

if _, err := tmpFile.Write(content); err != nil {
slog.Error("Error writing to temp file", "file", tmpFile.Name(), "error", err)
tmpFile.Close()
continue
}

if err := tmpFile.Close(); err != nil {
slog.Error("Error closing temp file", "file", tmpFile.Name(), "error", err)
continue
}

if err := os.Rename(tmpFile.Name(), path); err != nil {
slog.Error("Error moving temp file to final location", "src", tmpFile.Name(), "dst", path, "error", err)
continue
}

slog.Info("Updated file", "path", path)
}

_, err = file.Write(res.Body)
if err != nil {
slog.Error("Error writing to file", "filename", res.Filename)
// Apply NGINX config after all files updated
if err := applyNginxConfig(); err != nil {
slog.Error("Error applying NGINX config", "error", err)
http.Error(w, "failed to apply nginx config", http.StatusInternalServerError)
return
}

err = applyNginxConfig()
if err != nil {
slog.Error("Error applying nginx config", "error", err, "filename", res.Filename)
return
}
w.WriteHeader(http.StatusOK)
slog.Info("Config update applied successfully")
}

func applyNginxConfig() error {
slog.Info("reloading nginx config")
cmd := exec.Command("nginx", "-t")

output, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("nginx config test failed: %s", string(output))
}

cmd = exec.Command("nginx", "-s", "reload")

output, err = cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("nginx reload failed: %s", string(output))
Expand Down
9 changes: 8 additions & 1 deletion dataplane/nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,12 @@ http{
'"$bytes_sent" "$request_length" "$request_time" '
'"$gzip_ratio" $server_protocol ';

include /etc/nginx/users/*/nginx.conf;
include /etc/nginx/users/*/zone.conf;

server {
listen 8080;

include /etc/nginx/users/*/nginx.conf;
}

}
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ services:
volumes:
- "./config:/etc/config"
- "./src/templates/nginx.conf.tmpl:/etc/nginx/nginx.conf.tmpl:ro"
- "./src/templates/zone.conf.tmpl:/etc/nginx/zone.conf.tmpl:ro"
- "./src/config/init.sql:/var/lib/init.sql:ro"
restart: unless-stopped
depends_on:
Expand Down
86 changes: 43 additions & 43 deletions management/main.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
package main

import (
"fyp-api-gateway/management/auth"
"fyp-api-gateway/management/handler"
"log/slog"
"net/http"
)

func main() {
mux := http.NewServeMux()

// frontend routes
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
//mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// http.Redirect(w, r, "/", http.StatusSeeOther)
//})
mux.HandleFunc("/auth", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./static/auth.html")
})
mux.HandleFunc("/config", auth.RequireSession(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./static/config.html")
}))
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./static/index.html")
})

// account initialisation routes
mux.HandleFunc("/api/signup", auth.Signup)
mux.HandleFunc("/api/login", auth.Login)
mux.HandleFunc("/file/gateway", auth.RequireSession(handler.Gateway))

// config routes
mux.HandleFunc("/file/upload", handler.HandleNewConfig)
mux.HandleFunc("/file/findings", handler.RecvFindings)
mux.HandleFunc("/file/retrieve", handler.Findings)
mux.HandleFunc("/file/accept", handler.HandleAcceptChanges)

err := http.ListenAndServe(":81", mux)
if err != nil {
slog.Error("could not start management plane", "error", err)
}
}
package main
import (
"fyp-api-gateway/management/auth"
"fyp-api-gateway/management/handler"
"log/slog"
"net/http"
)
func main() {
mux := http.NewServeMux()
// frontend routes
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
//mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// http.Redirect(w, r, "/", http.StatusSeeOther)
//})
mux.HandleFunc("/auth", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./static/auth.html")
})
mux.HandleFunc("/config", auth.RequireSession(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./static/config.html")
}))
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./static/index.html")
})
// account initialisation routes
mux.HandleFunc("/api/signup", auth.Signup)
mux.HandleFunc("/api/login", auth.Login)
mux.HandleFunc("/file/gateway", auth.RequireSession(handler.Gateway))
// config routes
mux.HandleFunc("/file/upload", handler.HandleNewConfig)
mux.HandleFunc("/file/findings", handler.RecvFindings)
mux.HandleFunc("/file/retrieve", handler.Findings)
mux.HandleFunc("/file/accept", handler.HandleAcceptChanges)
err := http.ListenAndServe(":81", mux)
if err != nil {
slog.Error("could not start management plane", "error", err)
}
}
1 change: 1 addition & 0 deletions management/static/auth.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<a href="/">Home</a>
<a href="/auth">Signup/Login</a>
<a href="/config">Config File</a>
<a href="http://localhost:3000">Dashboard</a>
</nav>
</header>

Expand Down
1 change: 1 addition & 0 deletions management/static/config.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<a href="/">Home</a>
<a href="/auth">Signup/Login</a>
<a href="/config">Config File</a>
<a href="http://localhost:3000">Dashboard</a>
</nav>
</header>

Expand Down
Loading
Loading