Adds JWT token checks
parent
051cb65495
commit
5521229f82
|
@ -15,6 +15,6 @@ All notable changes to this project will be documented in this file.
|
|||
### Added
|
||||
- Initial version in PHP
|
||||
- New version in folder "go", written in Go
|
||||
- Added endpoints for /nginx, /prosody, /jicofo, /jvb
|
||||
- Added endpoints for /nginx, /prosody, /jicofo, /jvb, /jibri
|
||||
- Added a config file and default values
|
||||
- Initial vesion of a build script
|
||||
|
|
|
@ -2,4 +2,7 @@ module jilo-agent
|
|||
|
||||
go 1.22.6
|
||||
|
||||
require gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
# the port on which the agent will listen
|
||||
agent_port: 8081
|
||||
|
||||
# secret for checking JWT (same as in Jilo Web agent config)
|
||||
secret_key: "mysecretkey"
|
||||
|
||||
# the port we check for nginx
|
||||
nginx_port: 80
|
||||
|
||||
|
|
76
go/main.go
76
go/main.go
|
@ -12,9 +12,10 @@ Version: 0.1
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"gopkg.in/yaml.v2"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
|
@ -27,6 +28,7 @@ import (
|
|||
// Config holds the structure of the configuration file
|
||||
type Config struct {
|
||||
AgentPort int `yaml:"agent_port"`
|
||||
SecretKey string `yaml:"secret_key"`
|
||||
NginxPort int `yaml:"nginx_port"`
|
||||
ProsodyPort int `yaml:"prosody_port"`
|
||||
JicofoStatsURL string `yaml:"jicofo_stats_url"`
|
||||
|
@ -34,6 +36,13 @@ type Config struct {
|
|||
JibriHealthURL string `yaml:"jibri_health_url"`
|
||||
}
|
||||
|
||||
// Claims holds JWT access right
|
||||
type Claims struct {
|
||||
Username string `json:"sub"`
|
||||
Role string `json:"role"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
// NginxData holds the nginx data structure for the API response to /nginx
|
||||
type NginxData struct {
|
||||
NginxState string `json:"nginx_state"`
|
||||
|
@ -64,6 +73,8 @@ type JibriData struct {
|
|||
JibriHealthData map[string]interface{} `json:"jibri_health_data"`
|
||||
}
|
||||
|
||||
var secretKey []byte
|
||||
|
||||
// getServiceState checks the status of the speciied service
|
||||
func getServiceState(service string) string {
|
||||
output, err := exec.Command("systemctl", "is-active", service).Output()
|
||||
|
@ -145,6 +156,48 @@ func loadConfig(filename string) (Config) {
|
|||
return config
|
||||
}
|
||||
|
||||
// authenticationJWT handles the JWT auth
|
||||
func authenticationJWT(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
tokenString := r.Header.Get("Authorization")
|
||||
|
||||
// empty auth header
|
||||
if tokenString == "" {
|
||||
http.Error(w, "Auth header not received", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// remove "Bearer "
|
||||
if len(tokenString) > 7 && tokenString[:7] == "Bearer " {
|
||||
tokenString = tokenString[7:]
|
||||
}
|
||||
|
||||
claims := &Claims{}
|
||||
|
||||
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
|
||||
return secretKey, nil
|
||||
})
|
||||
|
||||
// JWT errors
|
||||
if err != nil {
|
||||
if err == jwt.ErrSignatureInvalid {
|
||||
http.Error(w, "Invalid JWT signature", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
http.Error(w, "Error parsing JWT", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
// JWT invalid
|
||||
if !token.Valid {
|
||||
http.Error(w, "Invali JWT token", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// nginxHandler handles the /nginx endpoint
|
||||
func nginxHandler(config Config, w http.ResponseWriter, r *http.Request) {
|
||||
data := NginxData {
|
||||
|
@ -201,23 +254,24 @@ func main() {
|
|||
|
||||
// load the configuration
|
||||
config := loadConfig("jilo-agent.conf")
|
||||
secretKey = []byte(config.SecretKey)
|
||||
|
||||
// endpoints
|
||||
http.HandleFunc("/nginx", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.Handle("/nginx", authenticationJWT(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
nginxHandler(config, w, r)
|
||||
})
|
||||
http.HandleFunc("/prosody", func(w http.ResponseWriter, r *http.Request) {
|
||||
})))
|
||||
http.Handle("/prosody", authenticationJWT(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
prosodyHandler(config, w, r)
|
||||
})
|
||||
http.HandleFunc("/jicofo", func(w http.ResponseWriter, r *http.Request) {
|
||||
})))
|
||||
http.Handle("/jicofo", authenticationJWT(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
jicofoHandler(config, w, r)
|
||||
})
|
||||
http.HandleFunc("/jvb", func(w http.ResponseWriter, r *http.Request) {
|
||||
})))
|
||||
http.Handle("/jvb", authenticationJWT(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
jvbHandler(config, w, r)
|
||||
})
|
||||
http.HandleFunc("/jibri", func(w http.ResponseWriter, r *http.Request) {
|
||||
})))
|
||||
http.Handle("/jibri", authenticationJWT(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
jibriHandler(config, w, r)
|
||||
})
|
||||
})))
|
||||
|
||||
// start the http server
|
||||
agentPortStr := fmt.Sprintf(":%d", config.AgentPort)
|
||||
|
|
Loading…
Reference in New Issue