package caddy_tailscale import ( "encoding/json" "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig" "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile" "github.com/caddyserver/caddy/v2/modules/caddyhttp" "github.com/caddyserver/caddy/v2/modules/caddyhttp/caddyauth" "github.com/caddyserver/caddy/v2/modules/caddyhttp/headers" "net/http" ) func init() { httpcaddyfile.RegisterDirective("tailscale_auth", parseCaddyfile) httpcaddyfile.RegisterDirec1tiveOrder("tailscale_auth", httpcaddyfile.After, "basic_auth") } // parseCaddyfile sets up the handler from Caddyfile tokens. Syntax: // // tailscale_auth [set_headers] // // See also for further examples: // - https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/caddyauth/caddyfile.go // - https://github.com/caddyserver/caddy/blob/master/modules/caddyhttp/reverseproxy/forwardauth/caddyfile.go func parseCaddyfile(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) { h.Next() // consume directive name handlers := []json.RawMessage{ caddyconfig.JSONModuleObject( caddyauth.Authentication{ ProvidersRaw: caddy.ModuleMap{ "tailscale": caddyconfig.JSON(new(TailscaleAuth), nil), }, }, "handler", "authentication", nil, ), } var setHeaders bool if h.Next() { if h.Val() == "set_headers" { setHeaders = true } else { return nil, h.Errf("unknown argument %#v", h.ValRaw()) } } headerOps := new(headers.HeaderOps) // If both the Set and Delete are set at the same time, Delete will take priority and prevent any headers from being // included in the request so we have to only do one or the other if setHeaders { headerOps.Set = http.Header{ "Tailscale-User-Id": []string{"{http.auth.user.id}"}, "Tailscale-User-Name": []string{"{http.auth.user.display_name}"}, "Tailscale-User-Login": []string{"{http.auth.user.login_name}"}, } } else { headerOps.Delete = []string{"Tailscale-User-Id", "Tailscale-User-Name", "Tailscale-User-Login"} } handlers = append(handlers, caddyconfig.JSONModuleObject( &headers.Handler{ Request: headerOps, }, "handler", "headers", nil, )) if h.NextArg() { return nil, h.Err("too many arguments") } return []httpcaddyfile.ConfigValue{ { Class: "route", Value: caddyhttp.Route{ HandlersRaw: handlers, }, }, }, nil }