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
62 changes: 32 additions & 30 deletions data/defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,39 @@ service:
logLevel: info

settings:
dataAliases:
"@message":
[
{ alias: msg, score: 100 },
{ alias: content, score: 99 },
{ alias: description, score: 98 },
{ alias: text, score: 20 },
{ alias: summary, score: 15 },
{ alias: details, score: 14 },
message:
fieldMappings:
"@message":
[
{ field: msg, score: 100 },
{ field: content, score: 99 },
{ field: description, score: 98 },
{ field: text, score: 20 },
{ field: summary, score: 15 },
{ field: details, score: 14 },

{ alias: data.message, score: 10 },
{ alias: data.content, score: 9 },
{ alias: data.description, score: 8 },
{ alias: data.text, score: 7 },
{ alias: data.summary, score: 6 },
{ alias: data.details, score: 5 },
{ field: data.message, score: 10 },
{ field: data.content, score: 9 },
{ field: data.description, score: 8 },
{ field: data.text, score: 7 },
{ field: data.summary, score: 6 },
{ field: data.details, score: 5 },

{ alias: body, score: 2 },
{ alias: data, score: 1 },
]
{ field: body, score: 2 },
{ field: data, score: 1 },
]

variables:
recipients: ${RECIPIENTS}
number: ${NUMBER}
variables:
recipients: ${RECIPIENTS}
number: ${NUMBER}

blockedEndpoints:
- /v1/about
- /v1/configuration
- /v1/devices
- /v1/register
- /v1/unregister
- /v1/qrcodelink
- /v1/accounts
- /v1/contacts
access:
endpoints:
- !/v1/about
- !/v1/configuration
- !/v1/devices
- !/v1/register
- !/v1/unregister
- !/v1/qrcodelink
- !/v1/accounts
- !/v1/contacts
5 changes: 3 additions & 2 deletions internals/proxy/middlewares/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"net/http"

"github.com/codeshelldev/secured-signal-api/utils/config"
"github.com/codeshelldev/secured-signal-api/utils/config/structure"
)

type Context struct {
Expand All @@ -23,7 +24,7 @@ type contextKey string

const tokenKey contextKey = "token"

func getSettingsByReq(req *http.Request) *config.SETTING_ {
func getSettingsByReq(req *http.Request) *structure.SETTINGS {
token, ok := req.Context().Value(tokenKey).(string)

if !ok {
Expand All @@ -33,7 +34,7 @@ func getSettingsByReq(req *http.Request) *config.SETTING_ {
return getSettings(token)
}

func getSettings(token string) *config.SETTING_ {
func getSettings(token string) *structure.SETTINGS {
settings, exists := config.ENV.SETTINGS[token]

if !exists || settings == nil {
Expand Down
32 changes: 21 additions & 11 deletions internals/proxy/middlewares/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@ func endpointsHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
settings := getSettingsByReq(req)

blockedEndpoints := settings.BLOCKED_ENDPOINTS
allowedEndpoints := settings.ALLOWED_ENDPOINTS
endpoints := settings.ACCESS.ENDPOINTS

if blockedEndpoints == nil && allowedEndpoints == nil {
blockedEndpoints = getSettings("*").BLOCKED_ENDPOINTS
if endpoints == nil {
endpoints = getSettings("*").ACCESS.ENDPOINTS
}

reqPath := req.URL.Path

if isBlocked(reqPath, allowedEndpoints, blockedEndpoints) {
if isBlocked(reqPath, endpoints) {
log.Warn("User tried to access blocked endpoint: ", reqPath)
http.Error(w, "Forbidden", http.StatusForbidden)
return
Expand All @@ -36,15 +35,26 @@ func endpointsHandler(next http.Handler) http.Handler {
})
}

func isBlocked(endpoint string, allowed []string, blocked []string) bool {
if blocked == nil {
blocked = []string{}
}
func getEndpoints(endpoints []string) ([]string, []string) {
blockedEndpoints := []string{}
allowedEndpoints := []string{}

for _, endpoint := range endpoints {
endpoint, block := strings.CutPrefix(endpoint, "!")

if allowed == nil {
allowed = []string{}
if block {
blockedEndpoints = append(blockedEndpoints, endpoint)
} else {
allowedEndpoints = append(allowedEndpoints, endpoint)
}
}

return allowedEndpoints, blockedEndpoints
}

func isBlocked(endpoint string, endpoints []string) bool {
allowed, blocked := getEndpoints(endpoints)

isExplicitlyBlocked := slices.ContainsFunc(blocked, func(try string) bool {
return strings.HasPrefix(endpoint, try)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@ import (
"net/http"
"strconv"

middlewareTypes "github.com/codeshelldev/secured-signal-api/internals/proxy/middlewares/types"
"github.com/codeshelldev/secured-signal-api/utils/config/structure"
jsonutils "github.com/codeshelldev/secured-signal-api/utils/jsonutils"
log "github.com/codeshelldev/secured-signal-api/utils/logger"
request "github.com/codeshelldev/secured-signal-api/utils/request"
)

var Aliases Middleware = Middleware{
Name: "Aliases",
Use: aliasesHandler,
var Mapping Middleware = Middleware{
Name: "Mapping",
Use: mappingHandler,
}

func aliasesHandler(next http.Handler) http.Handler {
func mappingHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
settings := getSettingsByReq(req)

dataAliases := settings.DATA_ALIASES
fieldMappings := settings.MESSAGE.FIELD_MAPPINGS

if dataAliases == nil {
dataAliases = getSettings("*").DATA_ALIASES
if fieldMappings == nil {
fieldMappings = getSettings("*").MESSAGE.FIELD_MAPPINGS
}

if settings.VARIABLES == nil {
settings.VARIABLES = getSettings("*").VARIABLES
if settings.MESSAGE.VARIABLES == nil {
settings.MESSAGE.VARIABLES = getSettings("*").MESSAGE.VARIABLES
}

body, err := request.GetReqBody(w, req)
Expand All @@ -43,7 +43,7 @@ func aliasesHandler(next http.Handler) http.Handler {
if !body.Empty {
bodyData = body.Data

aliasData := processDataAliases(dataAliases, bodyData)
aliasData := processFieldMappings(fieldMappings, bodyData)

for key, value := range aliasData {
prefix := key[:1]
Expand All @@ -55,7 +55,7 @@ func aliasesHandler(next http.Handler) http.Handler {
bodyData[keyWithoutPrefix] = value
modifiedBody = true
case ".":
settings.VARIABLES[keyWithoutPrefix] = value
settings.MESSAGE.VARIABLES[keyWithoutPrefix] = value
}
}
}
Expand Down Expand Up @@ -84,7 +84,7 @@ func aliasesHandler(next http.Handler) http.Handler {
})
}

func processDataAliases(aliases map[string][]middlewareTypes.DataAlias, data map[string]any) map[string]any {
func processFieldMappings(aliases map[string][]structure.FieldMapping, data map[string]any) map[string]any {
aliasData := map[string]any{}

for key, alias := range aliases {
Expand All @@ -98,27 +98,27 @@ func processDataAliases(aliases map[string][]middlewareTypes.DataAlias, data map
return aliasData
}

func getData(key string, aliases []middlewareTypes.DataAlias, data map[string]any) (string, any) {
func getData(key string, aliases []structure.FieldMapping, data map[string]any) (string, any) {
var best int
var value any

for _, alias := range aliases {
aliasValue, score, ok := processAlias(alias, data)
aliasValue, score, ok := processFieldMapping(alias, data)

if ok {
if score > best {
value = aliasValue
}

delete(data, alias.Alias)
delete(data, alias.Field)
}
}

return key, value
}

func processAlias(alias middlewareTypes.DataAlias, data map[string]any) (any, int, bool) {
aliasKey := alias.Alias
func processFieldMapping(alias structure.FieldMapping, data map[string]any) (any, int, bool) {
aliasKey := alias.Field

value, ok := jsonutils.GetByPath(aliasKey, data)

Expand Down
8 changes: 4 additions & 4 deletions internals/proxy/middlewares/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ func messageHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
settings := getSettingsByReq(req)

variables := settings.VARIABLES
messageTemplate := settings.MESSAGE_TEMPLATE
variables := settings.MESSAGE.VARIABLES
messageTemplate := settings.MESSAGE.TEMPLATE

if variables == nil {
variables = getSettings("*").VARIABLES
variables = getSettings("*").MESSAGE.VARIABLES
}

if messageTemplate == "" {
messageTemplate = getSettings("*").MESSAGE_TEMPLATE
messageTemplate = getSettings("*").MESSAGE.TEMPLATE
}

body, err := request.GetReqBody(w, req)
Expand Down
4 changes: 2 additions & 2 deletions internals/proxy/middlewares/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ var Template Middleware = Middleware{

func templateHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
variables := getSettingsByReq(req).VARIABLES
variables := getSettingsByReq(req).MESSAGE.VARIABLES

if variables == nil {
variables = getSettings("*").VARIABLES
variables = getSettings("*").MESSAGE.VARIABLES
}

body, err := request.GetReqBody(w, req)
Expand Down
9 changes: 0 additions & 9 deletions internals/proxy/middlewares/types/types.go

This file was deleted.

3 changes: 2 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import (

reverseProxy "github.com/codeshelldev/secured-signal-api/internals/proxy"
config "github.com/codeshelldev/secured-signal-api/utils/config"
"github.com/codeshelldev/secured-signal-api/utils/config/structure"
docker "github.com/codeshelldev/secured-signal-api/utils/docker"
log "github.com/codeshelldev/secured-signal-api/utils/logger"
)

var proxy reverseProxy.Proxy

var ENV *config.ENV_
var ENV *structure.ENV

func main() {
logLevel := os.Getenv("LOG_LEVEL")
Expand Down
49 changes: 16 additions & 33 deletions utils/config/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,20 @@ import (
"strconv"
"strings"

middlewareTypes "github.com/codeshelldev/secured-signal-api/internals/proxy/middlewares/types"
"github.com/codeshelldev/secured-signal-api/utils/config/structure"
jsonutils "github.com/codeshelldev/secured-signal-api/utils/jsonutils"
log "github.com/codeshelldev/secured-signal-api/utils/logger"

"github.com/knadh/koanf/parsers/yaml"
)

type ENV_ struct {
CONFIG_PATH string
DEFAULTS_PATH string
FAVICON_PATH string
TOKENS_DIR string
LOG_LEVEL string
PORT string
API_URL string
API_TOKENS []string
SETTINGS map[string]*SETTING_
INSECURE bool
}

type SETTING_ struct {
BLOCKED_ENDPOINTS []string `koanf:"blockedendpoints"`
ALLOWED_ENDPOINTS []string `koanf:"allowedendpoints"`
VARIABLES map[string]any `koanf:"variables"`
DATA_ALIASES map[string][]middlewareTypes.DataAlias `koanf:"dataaliases"`
MESSAGE_TEMPLATE string `koanf:"messagetemplate"`
}

var ENV *ENV_ = &ENV_{
var ENV *structure.ENV = &structure.ENV{
CONFIG_PATH: os.Getenv("CONFIG_PATH"),
DEFAULTS_PATH: os.Getenv("DEFAULTS_PATH"),
TOKENS_DIR: os.Getenv("TOKENS_DIR"),
FAVICON_PATH: os.Getenv("FAVICON_PATH"),
API_TOKENS: []string{},
SETTINGS: map[string]*SETTING_{},
SETTINGS: map[string]*structure.SETTINGS{},
INSECURE: false,
}

Expand Down Expand Up @@ -76,32 +55,36 @@ func InitEnv() {

ENV.API_URL = config.String("api.url")

var settings SETTING_
var settings structure.SETTINGS

transformChildren(config, "settings.variables", transformVariables)
transformChildren(config, "settings.message.variables", transformVariables)

config.Unmarshal("settings", &settings)

ENV.SETTINGS["*"] = &settings
}

func LoadDefaults() {
_, defErr := LoadFile(ENV.DEFAULTS_PATH, defaultsLayer, yaml.Parser())
_, err := LoadFile(ENV.DEFAULTS_PATH, defaultsLayer, yaml.Parser())

if defErr != nil {
if err != nil {
log.Warn("Could not Load Defaults", ENV.DEFAULTS_PATH)
}
}

func LoadConfig() {
_, conErr := LoadFile(ENV.CONFIG_PATH, userLayer, yaml.Parser())
_, err := LoadFile(ENV.CONFIG_PATH, userLayer, yaml.Parser())

if conErr != nil {
_, err := os.Stat(ENV.CONFIG_PATH)
if err != nil {
_, fsErr := os.Stat(ENV.CONFIG_PATH)

if !errors.Is(err, fs.ErrNotExist) {
log.Error("Could not Load Config ", ENV.CONFIG_PATH, ": ", conErr.Error())
// Config File doesn't exist
// => User is using Environment
if errors.Is(fsErr, fs.ErrNotExist) {
return
}

log.Error("Could not Load Config ", ENV.CONFIG_PATH, ": ", err.Error())
}
}

Expand Down
Loading