mirror of
https://github.com/amir20/dozzle.git
synced 2025-12-21 13:23:07 +01:00
feat: add support for custom headers for forward-proxy auth (#2642)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
5
main.go
5
main.go
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user