Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accounts & conf. added APIs to manager users #11

Merged
merged 11 commits into from
Mar 13, 2024
30 changes: 29 additions & 1 deletion api/configuration/configuration.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023 Nethesis S.r.l.
* Copyright (C) 2024 Nethesis S.r.l.
* http://www.nethesis.it - [email protected]
*
* SPDX-License-Identifier: GPL-2.0-only
Expand Down Expand Up @@ -35,9 +35,13 @@ type Configuration struct {

TokensDir string `json:"tokens_dir"`
CredentialsDir string `json:"credentials_dir"`
DataDir string `json:"data_dir"`

PromtailAddress string `json:"promtail_address"`
PromtailPort string `json:"promtail_port"`
PrometheusPath string `json:"prometheus_path"`
WebSSHPath string `json:"webssh_path"`
GrafanaPath string `json:"grafana_path"`

EasyRSAPath string `json:"easy_rsa_path"`

Expand Down Expand Up @@ -90,6 +94,12 @@ func Init() {
logs.Logs.Println("[CRITICAL][ENV] CREDENTIALS_DIR variable is empty")
os.Exit(1)
}
if os.Getenv("DATA_DIR") != "" {
Config.DataDir = os.Getenv("DATA_DIR")
} else {
logs.Logs.Println("[CRITICAL][ENV] DATA_DIR variable is empty")
os.Exit(1)
}

if os.Getenv("OVPN_DIR") != "" {
Config.OpenVPNDir = os.Getenv("OVPN_DIR")
Expand Down Expand Up @@ -145,6 +155,24 @@ func Init() {
logs.Logs.Println("[CRITICAL][ENV] PROMTAIL_PORT variable is empty")
os.Exit(1)
}
if os.Getenv("PROMETHEUS_PATH") != "" {
Config.PrometheusPath = os.Getenv("PROMETHEUS_PATH")
} else {
logs.Logs.Println("[CRITICAL][ENV] PROMETHEUS_PATH variable is empty")
os.Exit(1)
}
if os.Getenv("WEBSSH_PATH") != "" {
Config.WebSSHPath = os.Getenv("WEBSSH_PATH")
} else {
logs.Logs.Println("[CRITICAL][ENV] WEBSSH_PATH variable is empty")
os.Exit(1)
}
if os.Getenv("GRAFANA_PATH") != "" {
Config.GrafanaPath = os.Getenv("GRAFANA_PATH")
} else {
logs.Logs.Println("[CRITICAL][ENV] GRAFANA_PATH variable is empty")
os.Exit(1)
}

if os.Getenv("EASYRSA_PATH") != "" {
Config.EasyRSAPath = os.Getenv("EASYRSA_PATH")
Expand Down
1 change: 1 addition & 0 deletions api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ require (
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
Expand Down
2 changes: 2 additions & 0 deletions api/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
22 changes: 21 additions & 1 deletion api/main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023 Nethesis S.r.l.
* Copyright (C) 2024 Nethesis S.r.l.
* http://www.nethesis.it - [email protected]
*
* SPDX-License-Identifier: GPL-2.0-only
Expand All @@ -25,6 +25,7 @@ import (
"github.com/NethServer/nethsecurity-controller/api/methods"
"github.com/NethServer/nethsecurity-controller/api/middleware"
"github.com/NethServer/nethsecurity-controller/api/socket"
"github.com/NethServer/nethsecurity-controller/api/storage"
)

// @title NethSecurity Controller API Server
Expand All @@ -48,6 +49,9 @@ func main() {
// init configuration
configuration.Init()

// init storage
storage.Init()

// init globa vars
global.Init()

Expand Down Expand Up @@ -90,6 +94,22 @@ func main() {
// refresh handler
api.GET("/refresh", middleware.InstanceJWT().RefreshHandler)

// accounts APIs
accounts := api.Group("/accounts")
{
accounts.GET("", methods.GetAccounts)
accounts.GET("/:account_id", methods.GetAccount)
accounts.POST("", methods.AddAccount)
accounts.PUT("/:account_id", methods.UpdateAccount)
accounts.DELETE("/:account_id", methods.DeleteAccount)
}

// default APIs
defaults := api.Group("/defaults")
{
defaults.GET("", methods.GetDefaults)
}

// units APIs
units := api.Group("/units")
{
Expand Down
232 changes: 232 additions & 0 deletions api/methods/account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/*
* Copyright (C) 2024 Nethesis S.r.l.
* http://www.nethesis.it - [email protected]
*
* SPDX-License-Identifier: GPL-2.0-only
*
* author: Edoardo Spadoni <[email protected]>
*/

package methods

import (
"net/http"
"time"

"github.com/NethServer/nethsecurity-api/response"
"github.com/NethServer/nethsecurity-controller/api/models"
"github.com/NethServer/nethsecurity-controller/api/storage"
"github.com/fatih/structs"

jwt "github.com/appleboy/gin-jwt/v2"
"github.com/gin-gonic/gin"
)

func GetAccounts(c *gin.Context) {
// check auth for not admin users
isAdmin, _ := storage.IsAdmin(jwt.ExtractClaims(c)["id"].(string))
if !isAdmin {
c.JSON(http.StatusForbidden, structs.Map(response.StatusForbidden{
Code: 403,
Message: "can't access this resource",
Data: nil,
}))
return
}

// execute query
accounts, err := storage.GetAccounts()

if err != nil {
c.JSON(http.StatusInternalServerError, structs.Map(response.StatusInternalServerError{
Code: 500,
Message: "get accounts error",
Data: err.Error(),
}))
return
}

// check results
if len(accounts) == 0 {
c.JSON(http.StatusNotFound, structs.Map(response.StatusNotFound{
Code: 404,
Message: "not found",
Data: nil,
}))
return
}

// return ok
c.JSON(http.StatusOK, structs.Map(response.StatusOK{
Code: 200,
Message: "success",
Data: gin.H{"accounts": accounts, "total": len(accounts)},
}))
}

func GetAccount(c *gin.Context) {
// check auth for not admin users
isAdmin, _ := storage.IsAdmin(jwt.ExtractClaims(c)["id"].(string))
if !isAdmin {
c.JSON(http.StatusForbidden, structs.Map(response.StatusForbidden{
Code: 403,
Message: "can't access this resource",
Data: nil,
}))
return
}

// get account id
accountID := c.Param("account_id")

// execute query
accounts, err := storage.GetAccount(accountID)

if err != nil {
c.JSON(http.StatusInternalServerError, structs.Map(response.StatusInternalServerError{
Code: 500,
Message: "get account error",
Data: err.Error(),
}))
return
}

// check results
if len(accounts) == 0 {
c.JSON(http.StatusNotFound, structs.Map(response.StatusNotFound{
Code: 404,
Message: "not found",
Data: nil,
}))
return
}

// return ok
c.JSON(http.StatusOK, structs.Map(response.StatusOK{
Code: 200,
Message: "success",
Data: gin.H{"account": accounts[0]},
}))
}

func AddAccount(c *gin.Context) {
// check auth for not admin users
isAdmin, _ := storage.IsAdmin(jwt.ExtractClaims(c)["id"].(string))
if !isAdmin {
c.JSON(http.StatusForbidden, structs.Map(response.StatusForbidden{
Code: 403,
Message: "can't access this resource",
Data: nil,
}))
return
}

// get account fields
var json models.Account
if err := c.BindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": "request fields malformed", "error": err.Error()})
return
}

// create account
json.Created = time.Now()
err := storage.AddAccount(json)
gsanchietti marked this conversation as resolved.
Show resolved Hide resolved

// check results
if err != nil {
c.JSON(http.StatusInternalServerError, structs.Map(response.StatusInternalServerError{
Code: 500,
Message: "add account error",
Data: err.Error(),
}))
return
}

// return ok
c.JSON(http.StatusCreated, structs.Map(response.StatusCreated{
Code: 201,
Message: "success",
Data: nil,
}))
}

func UpdateAccount(c *gin.Context) {
// get account id
accountID := c.Param("account_id")

// check is admin
isAdmin, id := storage.IsAdmin(jwt.ExtractClaims(c)["id"].(string))

// check authorization
if !isAdmin && accountID != id {
c.JSON(http.StatusForbidden, structs.Map(response.StatusForbidden{
Code: 403,
Message: "can't access this resource",
Data: nil,
}))
return
}

// get account fields
var json models.Account
if err := c.BindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": "request fields malformed", "error": err.Error()})
return
}

// update account
err := storage.UpdateAccount(accountID, json)

// check results
if err != nil {
c.JSON(http.StatusInternalServerError, structs.Map(response.StatusInternalServerError{
Code: 500,
Message: "add account error",
Data: err.Error(),
}))
return
}

// return ok
c.JSON(http.StatusOK, structs.Map(response.StatusOK{
Code: 200,
Message: "success",
Data: nil,
}))
}

func DeleteAccount(c *gin.Context) {
// check auth
isAdmin, _ := storage.IsAdmin(jwt.ExtractClaims(c)["id"].(string))
if !isAdmin {
c.JSON(http.StatusForbidden, structs.Map(response.StatusForbidden{
Code: 403,
Message: "can't access this resource",
Data: nil,
}))
return
}

// get account id
accountID := c.Param("account_id")

// execute query
err := storage.DeleteAccount(accountID)

// check results
if err != nil {
c.JSON(http.StatusInternalServerError, structs.Map(response.StatusInternalServerError{
Code: 500,
Message: "delete account error",
Data: err.Error(),
}))
return
}

// return ok
c.JSON(http.StatusOK, structs.Map(response.StatusOK{
Code: 200,
Message: "success",
Data: nil,
}))
}
13 changes: 2 additions & 11 deletions api/methods/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ func SetTokenValidation(username string, token string) bool {
_, err := f.WriteString(token + "\n")

// check error
if err != nil {
return false
}

return true
return err == nil
}

func DelTokenValidation(username string, token string) bool {
Expand All @@ -64,10 +60,5 @@ func DelTokenValidation(username string, token string) bool {
_, err := f.WriteString(strings.TrimSpace(res) + "\n")

// check error
if err != nil {
return false
}

return true

return err == nil
}
Loading
Loading