1
0
mirror of https://github.com/amir20/dozzle.git synced 2025-12-21 21:33:18 +01:00

feat: add support for custom headers for forward-proxy auth (#2642)

This commit is contained in:
Ankit R Gadiya
2024-01-01 13:59:14 +09:00
committed by GitHub
parent 77789aca73
commit ed43889e3b
4 changed files with 50 additions and 7 deletions

View File

@@ -178,6 +178,39 @@ notifier:
Valid SSL keys are required because Authelia only supports SSL.
### Setting up Dozzle with Cloudflare Zero Trust
Cloudflare Zero Trust is a service for authenticated access to selfhosted
software. This section defines how Dozzle can be setup to use Cloudflare Zero
Trust for authentication.
::: code-group
```yaml [docker-compose.yml]
version: "3.3"
services:
dozzle:
image: amir20/dozzle:latest
networks:
- net
environment:
DOZZLE_AUTH_PROVIDER: forward-proxy
DOZZLE_AUTH_HEADER_USER: Cf-Access-Authenticated-User-Email
DOZZLE_AUTH_HEADER_EMAIL: Cf-Access-Authenticated-User-Email
DOZZLE_AUTH_HEADER_NAME: Cf-Access-Authenticated-User-Email
volumes:
- /var/run/docker.sock:/var/run/docker.sock
expose:
- 8080
restart: unless-stopped
```
After running the Dozzle container, configure the Application in Cloudflare Zero
Trust dashboard by following the
[guide](https://developers.cloudflare.com/cloudflare-one/applications/configure-apps/self-hosted-apps/)
here.
## File Based User Management
Dozzle supports multi-user authentication by setting `--auth-provider` to `simple`. In this mode, Dozzle will try to read `/data/users.yml`. The content of the file looks like

View File

@@ -15,6 +15,9 @@ type contextKey string
const remoteUser contextKey = "remoteUser"
type proxyAuthContext struct {
headerUser string
headerEmail string
headerName string
}
func hashEmail(email string) string {
@@ -25,14 +28,18 @@ func hashEmail(email string) string {
return hex.EncodeToString(hash[:])
}
func NewForwardProxyAuth() *proxyAuthContext {
return &proxyAuthContext{}
func NewForwardProxyAuth(user, email, name string) *proxyAuthContext {
return &proxyAuthContext{
headerUser: user,
headerEmail: email,
headerName: name,
}
}
func (p *proxyAuthContext) AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Remote-User") != "" {
user := newUser(r.Header.Get("Remote-User"), r.Header.Get("Remote-Email"), r.Header.Get("Remote-Name"))
if r.Header.Get(p.headerUser) != "" {
user := newUser(r.Header.Get(p.headerUser), r.Header.Get(p.headerEmail), r.Header.Get(p.headerName))
ctx := context.WithValue(r.Context(), remoteUser, user)
next.ServeHTTP(w, r.WithContext(ctx))
} else {

View File

@@ -20,7 +20,7 @@ func Test_createRoutes_proxy_missing_headers(t *testing.T) {
handler := createHandler(nil, afero.NewIOFS(fs), Config{Base: "/",
Authorization: Authorization{
Provider: FORWARD_PROXY,
Authorizer: auth.NewForwardProxyAuth(),
Authorizer: auth.NewForwardProxyAuth("Remote-User", "Remote-Email", "Remote-Name"),
},
})
req, err := http.NewRequest("GET", "/", nil)
@@ -39,7 +39,7 @@ func Test_createRoutes_proxy_happy(t *testing.T) {
handler := createHandler(nil, afero.NewIOFS(fs), Config{Base: "/",
Authorization: Authorization{
Provider: FORWARD_PROXY,
Authorizer: auth.NewForwardProxyAuth(),
Authorizer: auth.NewForwardProxyAuth("Remote-User", "Remote-Email", "Remote-Name"),
},
})
req, err := http.NewRequest("GET", "/", nil)

View File

@@ -44,6 +44,9 @@ type args struct {
Level string `arg:"env:DOZZLE_LEVEL" default:"info" help:"set Dozzle log level. Use debug for more logging."`
Username string `arg:"env:DOZZLE_USERNAME" help:"sets the username for auth."`
Password string `arg:"env:DOZZLE_PASSWORD" help:"sets password for auth"`
AuthHeaderUser string `arg:"env:DOZZLE_AUTH_HEADER_USER" default:"Remote-User" help:"sets the HTTP Header to use for username in Forward Proxy configuration."`
AuthHeaderEmail string `arg:"env:DOZZLE_AUTH_HEADER_EMAIL" default:"Remote-Email" help:"sets the HTTP Header to use for email in Forward Proxy configuration."`
AuthHeaderName string `arg:"env:DOZZLE_AUTH_HEADER_NAME" default:"Remote-Name" help:"sets the HTTP Header to use for name in Forward Proxy configuration."`
NoAnalytics bool `arg:"--no-analytics,env:DOZZLE_NO_ANALYTICS" help:"disables anonymous analytics"`
WaitForDockerSeconds int `arg:"--wait-for-docker-seconds,env:DOZZLE_WAIT_FOR_DOCKER_SECONDS" help:"wait for docker to be available for at most this many seconds before starting the server."`
FilterStrings []string `arg:"env:DOZZLE_FILTER,--filter,separate" help:"filters docker containers using Docker syntax."`
@@ -168,7 +171,7 @@ func createServer(args args, clients map[string]web.DockerClient) *http.Server {
var authorizer web.Authorizer
if args.AuthProvider == "forward-proxy" {
provider = web.FORWARD_PROXY
authorizer = auth.NewForwardProxyAuth()
authorizer = auth.NewForwardProxyAuth(args.AuthHeaderUser, args.AuthHeaderEmail, args.AuthHeaderName)
} else if args.AuthProvider == "simple" {
provider = web.SIMPLE