mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-12-31 04:22:28 +00:00
wip
This commit is contained in:
@@ -57,7 +57,7 @@ func (app *BootstrapApp) initServices() (Services, error) {
|
|||||||
|
|
||||||
services.dockerService = dockerService
|
services.dockerService = dockerService
|
||||||
|
|
||||||
accessControlsService := service.NewAccessControlsService(dockerService)
|
accessControlsService := service.NewAccessControlsService(dockerService, app.config.Apps)
|
||||||
|
|
||||||
err = accessControlsService.Init()
|
err = accessControlsService.Init()
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ var RedirectCookieName = "tinyauth-redirect"
|
|||||||
// Main app config
|
// Main app config
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
Apps
|
||||||
AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"`
|
AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"`
|
||||||
LogLevel string `description:"Log level (trace, debug, info, warn, error)." yaml:"logLevel"`
|
LogLevel string `description:"Log level (trace, debug, info, warn, error)." yaml:"logLevel"`
|
||||||
ResourcesDir string `description:"The directory where resources are stored." yaml:"resourcesDir"`
|
ResourcesDir string `description:"The directory where resources are stored." yaml:"resourcesDir"`
|
||||||
@@ -156,61 +157,55 @@ type RedirectQuery struct {
|
|||||||
RedirectURI string `url:"redirect_uri"`
|
RedirectURI string `url:"redirect_uri"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Labels
|
// ACLs
|
||||||
|
|
||||||
type Apps struct {
|
type Apps struct {
|
||||||
Apps map[string]App
|
Apps map[string]App `description:"App ACLs configuration." yaml:"apps"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type App struct {
|
type App struct {
|
||||||
Config AppConfig
|
Config AppConfig `description:"App configuration." yaml:"config"`
|
||||||
Users AppUsers
|
Users AppUsers `description:"User access configuration." yaml:"users"`
|
||||||
OAuth AppOAuth
|
OAuth AppOAuth `description:"OAuth access configuration." yaml:"oauth"`
|
||||||
IP AppIP
|
IP AppIP `description:"IP access configuration." yaml:"ip"`
|
||||||
Response AppResponse
|
Response AppResponse `description:"Response customization." yaml:"response"`
|
||||||
Path AppPath
|
Path AppPath `description:"Path access configuration." yaml:"path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppConfig struct {
|
type AppConfig struct {
|
||||||
Domain string
|
Domain string `description:"The domain of the app." yaml:"domain"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppUsers struct {
|
type AppUsers struct {
|
||||||
Allow string
|
Allow string `description:"Comma-separated list of allowed users." yaml:"allow"`
|
||||||
Block string
|
Block string `description:"Comma-separated list of blocked users." yaml:"block"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppOAuth struct {
|
type AppOAuth struct {
|
||||||
Whitelist string
|
Whitelist string `description:"Comma-separated list of allowed OAuth groups." yaml:"whitelist"`
|
||||||
Groups string
|
Groups string `description:"Comma-separated list of required OAuth groups." yaml:"groups"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppIP struct {
|
type AppIP struct {
|
||||||
Allow []string
|
Allow []string `description:"List of allowed IPs or CIDR ranges." yaml:"allow"`
|
||||||
Block []string
|
Block []string `description:"List of blocked IPs or CIDR ranges." yaml:"block"`
|
||||||
Bypass []string
|
Bypass []string `description:"List of IPs or CIDR ranges that bypass authentication." yaml:"bypass"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppResponse struct {
|
type AppResponse struct {
|
||||||
Headers []string
|
Headers []string `description:"Custom headers to add to the response." yaml:"headers"`
|
||||||
BasicAuth AppBasicAuth
|
BasicAuth AppBasicAuth `description:"Basic authentication for the app." yaml:"basicAuth"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppBasicAuth struct {
|
type AppBasicAuth struct {
|
||||||
Username string
|
Username string `description:"Basic auth username." yaml:"username"`
|
||||||
Password string
|
Password string `description:"Basic auth password." yaml:"password"`
|
||||||
PasswordFile string
|
PasswordFile string `description:"Path to the file containing the basic auth password." yaml:"passwordFile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppPath struct {
|
type AppPath struct {
|
||||||
Allow string
|
Allow string `description:"Comma-separated list of allowed paths." yaml:"allow"`
|
||||||
Block string
|
Block string `description:"Comma-separated list of blocked paths." yaml:"block"`
|
||||||
}
|
|
||||||
|
|
||||||
// Flags
|
|
||||||
|
|
||||||
type Providers struct {
|
|
||||||
Providers map[string]OAuthServiceConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// API server
|
// API server
|
||||||
|
|||||||
@@ -1,122 +1,54 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/steveiliop56/tinyauth/internal/config"
|
"github.com/steveiliop56/tinyauth/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
|
||||||
Environment variable/flag based ACLs are disabled until v5 due to a technical challenge
|
|
||||||
with the current parsing logic.
|
|
||||||
|
|
||||||
The current parser works for simple OAuth provider configs like:
|
|
||||||
- PROVIDERS_MY_AMAZING_PROVIDER_CLIENT_ID
|
|
||||||
|
|
||||||
However, it breaks down when handling nested structs required for ACLs. The custom parsing
|
|
||||||
solution that worked for v4 OAuth providers is incompatible with the ACL parsing logic,
|
|
||||||
making the codebase unmaintainable and fragile.
|
|
||||||
|
|
||||||
A solution is being considered for v5 that would standardize the format to something like:
|
|
||||||
- TINYAUTH_PROVIDERS_GOOGLE_CLIENTSECRET
|
|
||||||
- TINYAUTH_APPS_MYAPP_CONFIG_DOMAIN
|
|
||||||
|
|
||||||
This would allow the Traefik parser to handle everything consistently, but requires a
|
|
||||||
config migration. Until this is resolved, environment-based ACLs are disabled and only
|
|
||||||
Docker label-based ACLs are supported.
|
|
||||||
|
|
||||||
See: https://discord.com/channels/1337450123600465984/1337459086270271538/1434986689935179838 for more information
|
|
||||||
*/
|
|
||||||
|
|
||||||
type AccessControlsService struct {
|
type AccessControlsService struct {
|
||||||
docker *DockerService
|
docker *DockerService
|
||||||
// envACLs config.Apps
|
config config.Apps
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAccessControlsService(docker *DockerService) *AccessControlsService {
|
func NewAccessControlsService(docker *DockerService, config config.Apps) *AccessControlsService {
|
||||||
return &AccessControlsService{
|
return &AccessControlsService{
|
||||||
docker: docker,
|
docker: docker,
|
||||||
|
config: config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (acls *AccessControlsService) Init() error {
|
func (acls *AccessControlsService) Init() error {
|
||||||
// acls.envACLs = config.Apps{}
|
return nil // No initialization needed
|
||||||
// env := os.Environ()
|
|
||||||
// appEnvVars := []string{}
|
|
||||||
|
|
||||||
// for _, e := range env {
|
|
||||||
// if strings.HasPrefix(e, "TINYAUTH_APPS_") {
|
|
||||||
// appEnvVars = append(appEnvVars, e)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// err := acls.loadEnvACLs(appEnvVars)
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return nil
|
|
||||||
|
|
||||||
return nil
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (acls *AccessControlsService) loadEnvACLs(appEnvVars []string) error {
|
func (acls *AccessControlsService) lookupConfigACLs(domain string) (config.App, error) {
|
||||||
// if len(appEnvVars) == 0 {
|
for app, config := range acls.config.Apps {
|
||||||
// return nil
|
if config.Config.Domain == domain {
|
||||||
// }
|
log.Debug().Str("name", app).Msg("Found matching container by domain")
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
// envAcls := map[string]string{}
|
if strings.SplitN(domain, ".", 2)[0] == app {
|
||||||
|
log.Debug().Str("name", app).Msg("Found matching container by app name")
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config.App{}, errors.New("no results")
|
||||||
|
}
|
||||||
|
|
||||||
// for _, e := range appEnvVars {
|
func (acls *AccessControlsService) GetAccessControls(domain string) (config.App, error) {
|
||||||
// parts := strings.SplitN(e, "=", 2)
|
// First check in the static config
|
||||||
// if len(parts) != 2 {
|
app, err := acls.lookupConfigACLs(domain)
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
|
|
||||||
// key := parts[0]
|
if err == nil {
|
||||||
// key = strings.ToLower(key)
|
log.Debug().Msg("Using ACls from static configuration")
|
||||||
// key = strings.ReplaceAll(key, "_", ".")
|
return app, nil
|
||||||
// value := parts[1]
|
}
|
||||||
// envAcls[key] = value
|
|
||||||
// }
|
|
||||||
|
|
||||||
// apps, err := decoders.DecodeLabels(envAcls)
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// acls.envACLs = apps
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (acls *AccessControlsService) lookupEnvACLs(appDomain string) *config.App {
|
|
||||||
// if len(acls.envACLs.Apps) == 0 {
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for appName, appACLs := range acls.envACLs.Apps {
|
|
||||||
// if appACLs.Config.Domain == appDomain {
|
|
||||||
// return &appACLs
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if strings.SplitN(appDomain, ".", 2)[0] == appName {
|
|
||||||
// return &appACLs
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (acls *AccessControlsService) GetAccessControls(appDomain string) (config.App, error) {
|
|
||||||
// First check environment variables
|
|
||||||
// envACLs := acls.lookupEnvACLs(appDomain)
|
|
||||||
|
|
||||||
// if envACLs != nil {
|
|
||||||
// log.Debug().Str("domain", appDomain).Msg("Found matching access controls in environment variables")
|
|
||||||
// return *envACLs, nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Fallback to Docker labels
|
// Fallback to Docker labels
|
||||||
return acls.docker.GetLabels(appDomain)
|
log.Debug().Msg("Falling back to Docker labels for ACLs")
|
||||||
|
return acls.docker.GetLabels(domain)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user