mirror of
https://github.com/ditkrg/traefik-users-blocker-plugin.git
synced 2026-01-22 19:16:57 +00:00
105 lines
2.2 KiB
Go
105 lines
2.2 KiB
Go
package traefik_users_blocker_plugin
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type Rule struct {
|
|
AllowedSubPaths []string `json:"allowedSubPaths,omitempty"`
|
|
}
|
|
|
|
type Path struct {
|
|
Path string `json:"base,omitempty"`
|
|
Rule Rule `json:"rule,omitempty"`
|
|
}
|
|
|
|
type Config struct {
|
|
UserIds []string `json:"userIds,omitempty"`
|
|
Paths []Path `json:"paths,omitempty"`
|
|
}
|
|
|
|
func CreateConfig() *Config {
|
|
return &Config{
|
|
UserIds: make([]string, 0),
|
|
Paths: make([]Path, 0),
|
|
}
|
|
}
|
|
|
|
type UsersBlocker struct {
|
|
next http.Handler
|
|
userId []string
|
|
paths []Path
|
|
name string
|
|
}
|
|
|
|
func New(ctx context.Context, next http.Handler, config *Config, name string) (http.Handler, error) {
|
|
if len(config.UserIds) == 0 {
|
|
return nil, fmt.Errorf("UserIds cannot be empty")
|
|
}
|
|
|
|
for _, path := range config.Paths {
|
|
if path.Path == "" {
|
|
return nil, fmt.Errorf("Paths.Path cannot be empty")
|
|
}
|
|
}
|
|
|
|
return &UsersBlocker{
|
|
next: next,
|
|
name: name,
|
|
userId: config.UserIds,
|
|
paths: config.Paths,
|
|
}, nil
|
|
}
|
|
|
|
func (a *UsersBlocker) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|
userId := req.Header["X-Auth-User-Id"][0]
|
|
|
|
message := fmt.Sprintf("{requestPath: %s, userId: %s}\n", req.URL.Path, userId)
|
|
os.Stdout.WriteString(message)
|
|
|
|
var isUserBlocked bool
|
|
|
|
for _, id := range a.userId {
|
|
if id == userId {
|
|
isUserBlocked = true
|
|
}
|
|
}
|
|
|
|
if !isUserBlocked {
|
|
a.next.ServeHTTP(rw, req)
|
|
return
|
|
}
|
|
|
|
for _, path := range a.paths {
|
|
isPathMatched := strings.HasPrefix(req.URL.Path, path.Path)
|
|
|
|
if !isPathMatched {
|
|
a.next.ServeHTTP(rw, req)
|
|
return
|
|
}
|
|
|
|
if len(path.Rule.AllowedSubPaths) == 0 {
|
|
message := fmt.Sprintf("blocked path %s (matched with %s) for user %s", req.URL.Path, path.Path, userId)
|
|
os.Stdout.WriteString(message)
|
|
http.Error(rw, message, http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
for _, allowedSubPath := range path.Rule.AllowedSubPaths {
|
|
isAllowedSubPathMatched := strings.HasPrefix(req.URL.Path, path.Path+allowedSubPath)
|
|
if !isAllowedSubPathMatched {
|
|
message := fmt.Sprintf("blocked path %s (matched with %s) for user %s", req.URL.Path, path.Path+path.Path+allowedSubPath, userId)
|
|
os.Stdout.WriteString(message)
|
|
http.Error(rw, message, http.StatusForbidden)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
a.next.ServeHTTP(rw, req)
|
|
}
|