119 lines
3.1 KiB
Go
119 lines
3.1 KiB
Go
package routers
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
|
|
"cloud.o-forge.io/core/oc-catalog/controllers"
|
|
"cloud.o-forge.io/core/oc-catalog/models"
|
|
"github.com/beego/beego/v2/core/logs"
|
|
beego "github.com/beego/beego/v2/server/web"
|
|
"github.com/beego/beego/v2/server/web/context"
|
|
"github.com/beego/beego/v2/server/web/swagger"
|
|
)
|
|
|
|
func setStatus403(ctx *context.Context) {
|
|
ctx.Output.SetStatus(403)
|
|
ctx.Output.Body([]byte(""))
|
|
}
|
|
|
|
// TODO: Force swagger regeneration during startup to ensure consistency
|
|
func initAuthMiddleware() {
|
|
var FilterAuthTags = func(ctx *context.Context) {
|
|
patternMatch := ctx.Input.GetData("RouterPattern").(string)
|
|
|
|
patternMatchPath := strings.Replace(patternMatch, rootapi.BasePath, "", 1)
|
|
|
|
//Discovery path
|
|
if patternMatch == "/" {
|
|
return
|
|
}
|
|
|
|
// First letter Uppercase and the rest lowercase
|
|
reqMethod := strings.ToUpper(string(ctx.Request.Method[0])) + strings.ToLower(string(ctx.Request.Method[1:]))
|
|
|
|
val := reflect.ValueOf(rootapi.Paths[patternMatchPath]).
|
|
Elem().FieldByName(reqMethod).
|
|
Elem().Interface().(swagger.Operation)
|
|
|
|
// Make sure never omit a security declaration
|
|
canaryVar := false
|
|
|
|
for _, securityItem := range val.Security {
|
|
canaryVar = true
|
|
|
|
for securityItemName := range securityItem {
|
|
switch t := rootapi.SecurityDefinitions[securityItemName]; t.Type {
|
|
case "basic":
|
|
user, pass, containBasic := ctx.Request.BasicAuth()
|
|
if containBasic {
|
|
if models.Login(user, pass) {
|
|
//TODO: Decide behaviour with multiple security
|
|
return
|
|
}
|
|
|
|
ctx.Output.SetStatus(403)
|
|
ctx.Output.Body([]byte("")) //We must create some kind of output to force beego abort the request
|
|
return
|
|
|
|
}
|
|
|
|
ctx.Output.Header("WWW-Authenticate", `Basic realm="Restricted"`)
|
|
ctx.Output.SetStatus(401)
|
|
ctx.Output.Body([]byte("")) //We must create some kind of output to force beego abort the request
|
|
return
|
|
|
|
case "apiKey":
|
|
var jwtTokenString string
|
|
|
|
switch t.In {
|
|
case "header":
|
|
jwtTokenString = ctx.Request.Header.Get(t.Name)
|
|
case "query":
|
|
jwtTokenString = ctx.Request.URL.Query().Get(t.Name)
|
|
default:
|
|
logs.Warn("BUG: API auth with token of type " + t.In + " not implemented.")
|
|
setStatus403(ctx)
|
|
return
|
|
}
|
|
|
|
if jwtTokenString != "" {
|
|
// We have a token
|
|
|
|
_, err := controllers.IsValidToken(jwtTokenString)
|
|
if err != nil {
|
|
//Bad token
|
|
ctx.Output.SetStatus(401)
|
|
ctx.Output.Body([]byte(err.Error()))
|
|
return
|
|
}
|
|
|
|
ctx.Input.SetData("jwtAPIToken", jwtTokenString)
|
|
return //Go to Controller
|
|
}
|
|
|
|
// No token at all
|
|
logs.Debug("No access token provided")
|
|
setStatus403(ctx)
|
|
return
|
|
default:
|
|
ctx.Output.SetStatus(501)
|
|
ctx.Output.Body([]byte("Authentication with " + t.Type + " not implemented"))
|
|
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if canaryVar {
|
|
// If we are here, that means some Security declaration exist and was skipped.
|
|
// Must avoid giving access, but should inform about it
|
|
|
|
logs.Critical("Probably a BUG related to authentication process")
|
|
setStatus403(ctx)
|
|
}
|
|
}
|
|
|
|
beego.InsertFilter("/*", beego.BeforeExec, FilterAuthTags)
|
|
}
|