mirror of
https://github.com/goauthentik/authentik
synced 2026-04-25 17:15:26 +02:00
root: allow listening on multiple IPs (#20930)
This commit is contained in:
committed by
GitHub
parent
545b1e8f19
commit
4dfdf9afa3
@@ -32,12 +32,18 @@ postgresql:
|
|||||||
# host: replica1.example.com
|
# host: replica1.example.com
|
||||||
|
|
||||||
listen:
|
listen:
|
||||||
http: 0.0.0.0:9000
|
http:
|
||||||
https: 0.0.0.0:9443
|
- "[::]:9000"
|
||||||
ldap: 0.0.0.0:3389
|
https:
|
||||||
ldaps: 0.0.0.0:6636
|
- "[::]:9443"
|
||||||
radius: 0.0.0.0:1812
|
ldap:
|
||||||
metrics: 0.0.0.0:9300
|
- "[::]:3389"
|
||||||
|
ldaps:
|
||||||
|
- "[::]:6636"
|
||||||
|
radius:
|
||||||
|
- "[::]:1812"
|
||||||
|
metrics:
|
||||||
|
- "[::]:9300"
|
||||||
debug: 0.0.0.0:9900
|
debug: 0.0.0.0:9900
|
||||||
debug_py: 0.0.0.0:9901
|
debug_py: 0.0.0.0:9901
|
||||||
trusted_proxy_cidrs:
|
trusted_proxy_cidrs:
|
||||||
|
|||||||
@@ -224,7 +224,10 @@ class WorkerHealthcheckMiddleware(Middleware):
|
|||||||
thread: HTTPServerThread | None
|
thread: HTTPServerThread | None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
host, _, port = CONFIG.get("listen.http").rpartition(":")
|
listen = CONFIG.get("listen.http", ["[::]:9000"])
|
||||||
|
if isinstance(listen, str):
|
||||||
|
listen = listen.split(",")
|
||||||
|
host, _, port = listen[0].rpartition(":")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
port = int(port)
|
port = int(port)
|
||||||
@@ -323,7 +326,10 @@ class MetricsMiddleware(BaseMetricsMiddleware):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
def after_worker_boot(self, broker: Broker, worker: Worker):
|
def after_worker_boot(self, broker: Broker, worker: Worker):
|
||||||
addr, _, port = CONFIG.get("listen.metrics").rpartition(":")
|
listen = CONFIG.get("listen.metrics", ["[::]:9300"])
|
||||||
|
if isinstance(listen, str):
|
||||||
|
listen = listen.split(",")
|
||||||
|
addr, _, port = listen[0].rpartition(":")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
port = int(port)
|
port = int(port)
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -12,7 +14,8 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"goauthentik.io/internal/config"
|
"goauthentik.io/internal/config"
|
||||||
"goauthentik.io/internal/utils/web"
|
utils "goauthentik.io/internal/utils/web"
|
||||||
|
"goauthentik.io/internal/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
var workerPidFile = path.Join(os.TempDir(), "authentik-worker.pid")
|
var workerPidFile = path.Join(os.TempDir(), "authentik-worker.pid")
|
||||||
@@ -44,9 +47,15 @@ func init() {
|
|||||||
|
|
||||||
func checkServer() int {
|
func checkServer() int {
|
||||||
h := &http.Client{
|
h := &http.Client{
|
||||||
Transport: web.NewUserAgentTransport("goauthentik.io/healthcheck", http.DefaultTransport),
|
Transport: utils.NewUserAgentTransport("goauthentik.io/healthcheck",
|
||||||
|
&http.Transport{
|
||||||
|
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||||
|
return net.Dial("unix", path.Join(os.TempDir(), web.SocketName))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
url := fmt.Sprintf("http://%s%s-/health/live/", config.Get().Listen.HTTP, config.Get().Web.Path)
|
url := fmt.Sprintf("http://localhost%s-/health/live/", config.Get().Web.Path)
|
||||||
res, err := h.Head(url)
|
res, err := h.Head(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Warning("failed to send healthcheck request")
|
log.WithError(err).Warning("failed to send healthcheck request")
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/getsentry/sentry-go"
|
"github.com/getsentry/sentry-go"
|
||||||
@@ -51,9 +52,10 @@ var rootCmd = &cobra.Command{
|
|||||||
ex := common.Init()
|
ex := common.Init()
|
||||||
defer common.Defer()
|
defer common.Defer()
|
||||||
|
|
||||||
u, err := url.Parse(fmt.Sprintf("http://%s%s", config.Get().Listen.HTTP, config.Get().Web.Path))
|
u := url.URL{
|
||||||
if err != nil {
|
Scheme: "unix",
|
||||||
panic(err)
|
Host: fmt.Sprintf("%s/%s", os.TempDir(), web.SocketName),
|
||||||
|
Path: config.Get().Web.Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
ws := web.NewWebServer()
|
ws := web.NewWebServer()
|
||||||
@@ -70,13 +72,13 @@ var rootCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func attemptProxyStart(ws *web.WebServer, u *url.URL) {
|
func attemptProxyStart(ws *web.WebServer, u url.URL) {
|
||||||
maxTries := 100
|
maxTries := 100
|
||||||
attempt := 0
|
attempt := 0
|
||||||
l := log.WithField("logger", "authentik.server")
|
l := log.WithField("logger", "authentik.server")
|
||||||
for {
|
for {
|
||||||
l.Debug("attempting to init outpost")
|
l.Debug("attempting to init outpost")
|
||||||
ac := ak.NewAPIController(*u, config.Get().SecretKey)
|
ac := ak.NewAPIController(u, config.Get().SecretKey)
|
||||||
if ac == nil {
|
if ac == nil {
|
||||||
attempt += 1
|
attempt += 1
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ type PostgreSQLConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListenConfig struct {
|
type ListenConfig struct {
|
||||||
HTTP string `yaml:"http" env:"HTTP, overwrite"`
|
HTTP []string `yaml:"http" env:"HTTP, overwrite"`
|
||||||
HTTPS string `yaml:"https" env:"HTTPS, overwrite"`
|
HTTPS []string `yaml:"https" env:"HTTPS, overwrite"`
|
||||||
LDAP string `yaml:"ldap" env:"LDAP, overwrite"`
|
LDAP []string `yaml:"ldap" env:"LDAP, overwrite"`
|
||||||
LDAPS string `yaml:"ldaps" env:"LDAPS, overwrite"`
|
LDAPS []string `yaml:"ldaps" env:"LDAPS, overwrite"`
|
||||||
Radius string `yaml:"radius" env:"RADIUS, overwrite"`
|
Radius []string `yaml:"radius" env:"RADIUS, overwrite"`
|
||||||
Metrics string `yaml:"metrics" env:"METRICS, overwrite"`
|
Metrics []string `yaml:"metrics" env:"METRICS, overwrite"`
|
||||||
Debug string `yaml:"debug" env:"DEBUG, overwrite"`
|
Debug string `yaml:"debug" env:"DEBUG, overwrite"`
|
||||||
TrustedProxyCIDRs []string `yaml:"trusted_proxy_cidrs" env:"TRUSTED_PROXY_CIDRS, overwrite"`
|
TrustedProxyCIDRs []string `yaml:"trusted_proxy_cidrs" env:"TRUSTED_PROXY_CIDRS, overwrite"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/fips140"
|
"crypto/fips140"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@@ -54,11 +55,30 @@ type APIController struct {
|
|||||||
// NewAPIController initialise new API Controller instance from URL and API token
|
// NewAPIController initialise new API Controller instance from URL and API token
|
||||||
func NewAPIController(akURL url.URL, token string) *APIController {
|
func NewAPIController(akURL url.URL, token string) *APIController {
|
||||||
rsp := sentry.StartSpan(context.Background(), "authentik.outposts.init")
|
rsp := sentry.StartSpan(context.Background(), "authentik.outposts.init")
|
||||||
|
log := log.WithField("logger", "authentik.outpost.ak-api-controller")
|
||||||
|
|
||||||
apiConfig := api.NewConfiguration()
|
originalAkURL := akURL
|
||||||
apiConfig.Host = akURL.Host
|
var client http.Client
|
||||||
apiConfig.Scheme = akURL.Scheme
|
if akURL.Scheme == "unix" {
|
||||||
apiConfig.HTTPClient = &http.Client{
|
log.WithField("host", akURL.Host).WithField("path", akURL.Path).Debug("using unix socket")
|
||||||
|
socketPath := akURL.Host
|
||||||
|
client = http.Client{
|
||||||
|
Transport: web.NewUserAgentTransport(
|
||||||
|
constants.UserAgentOutpost(),
|
||||||
|
web.NewTracingTransport(
|
||||||
|
rsp.Context(),
|
||||||
|
&http.Transport{
|
||||||
|
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||||
|
return net.Dial("unix", socketPath)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
akURL.Scheme = "http"
|
||||||
|
akURL.Host = "localhost"
|
||||||
|
} else {
|
||||||
|
client = http.Client{
|
||||||
Transport: web.NewUserAgentTransport(
|
Transport: web.NewUserAgentTransport(
|
||||||
constants.UserAgentOutpost(),
|
constants.UserAgentOutpost(),
|
||||||
web.NewTracingTransport(
|
web.NewTracingTransport(
|
||||||
@@ -67,6 +87,12 @@ func NewAPIController(akURL url.URL, token string) *APIController {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apiConfig := api.NewConfiguration()
|
||||||
|
apiConfig.Host = akURL.Host
|
||||||
|
apiConfig.Scheme = akURL.Scheme
|
||||||
|
apiConfig.HTTPClient = &client
|
||||||
apiConfig.Servers = api.ServerConfigurations{
|
apiConfig.Servers = api.ServerConfigurations{
|
||||||
{
|
{
|
||||||
URL: fmt.Sprintf("%sapi/v3", akURL.Path),
|
URL: fmt.Sprintf("%sapi/v3", akURL.Path),
|
||||||
@@ -77,8 +103,6 @@ func NewAPIController(akURL url.URL, token string) *APIController {
|
|||||||
// create the API client, with the transport
|
// create the API client, with the transport
|
||||||
apiClient := api.NewAPIClient(apiConfig)
|
apiClient := api.NewAPIClient(apiConfig)
|
||||||
|
|
||||||
log := log.WithField("logger", "authentik.outpost.ak-api-controller")
|
|
||||||
|
|
||||||
// Because we don't know the outpost UUID, we simply do a list and pick the first
|
// Because we don't know the outpost UUID, we simply do a list and pick the first
|
||||||
// The service account this token belongs to should only have access to a single outpost
|
// The service account this token belongs to should only have access to a single outpost
|
||||||
outposts, _ := retry.DoWithData[*api.PaginatedOutpostList](
|
outposts, _ := retry.DoWithData[*api.PaginatedOutpostList](
|
||||||
@@ -124,7 +148,7 @@ func NewAPIController(akURL url.URL, token string) *APIController {
|
|||||||
}
|
}
|
||||||
ac.logger.WithField("embedded", ac.IsEmbedded()).Info("Outpost mode")
|
ac.logger.WithField("embedded", ac.IsEmbedded()).Info("Outpost mode")
|
||||||
ac.logger.WithField("offset", ac.reloadOffset.String()).Debug("HA Reload offset")
|
ac.logger.WithField("offset", ac.reloadOffset.String()).Debug("HA Reload offset")
|
||||||
err = ac.initEvent(akURL, outpost.Pk)
|
err = ac.initEvent(originalAkURL, outpost.Pk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
go ac.recentEvents()
|
go ac.recentEvents()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -45,9 +46,19 @@ func (ac *APIController) initEvent(akURL url.URL, outpostUUID string) error {
|
|||||||
dialer := websocket.Dialer{
|
dialer := websocket.Dialer{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
HandshakeTimeout: 10 * time.Second,
|
HandshakeTimeout: 10 * time.Second,
|
||||||
TLSClientConfig: &tls.Config{
|
}
|
||||||
|
if akURL.Scheme == "unix" {
|
||||||
|
ac.logger.WithField("host", akURL.Host).WithField("path", akURL.Path).Debug("websocket is using unix connection")
|
||||||
|
socketPath := akURL.Host
|
||||||
|
dialer.NetDialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||||
|
return (&net.Dialer{}).DialContext(ctx, "unix", socketPath)
|
||||||
|
}
|
||||||
|
akURL.Scheme = "http"
|
||||||
|
akURL.Host = "localhost"
|
||||||
|
} else {
|
||||||
|
dialer.TLSClientConfig = &tls.Config{
|
||||||
InsecureSkipVerify: config.Get().AuthentikInsecure,
|
InsecureSkipVerify: config.Get().AuthentikInsecure,
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wsu := ac.getWebsocketURL(akURL, outpostUUID, query).String()
|
wsu := ac.getWebsocketURL(akURL, outpostUUID, query).String()
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
package healthcheck
|
package healthcheck
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"goauthentik.io/internal/config"
|
"goauthentik.io/internal/config"
|
||||||
|
"goauthentik.io/internal/outpost/ak"
|
||||||
"goauthentik.io/internal/utils/web"
|
"goauthentik.io/internal/utils/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,9 +24,15 @@ var Command = &cobra.Command{
|
|||||||
|
|
||||||
func check() int {
|
func check() int {
|
||||||
h := &http.Client{
|
h := &http.Client{
|
||||||
Transport: web.NewUserAgentTransport("goauthentik.io/healthcheck", http.DefaultTransport),
|
Transport: web.NewUserAgentTransport("goauthentik.io/healthcheck",
|
||||||
|
&http.Transport{
|
||||||
|
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||||
|
return net.Dial("unix", path.Join(os.TempDir(), ak.MetricsSocketName))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
url := fmt.Sprintf("http://%s/outpost.goauthentik.io/ping", config.Get().Listen.Metrics)
|
url := "http://localhost/outpost.goauthentik.io/ping"
|
||||||
res, err := h.Head(url)
|
res, err := h.Head(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Warning("failed to send healthcheck request")
|
log.WithError(err).Warning("failed to send healthcheck request")
|
||||||
|
|||||||
@@ -1,11 +1,21 @@
|
|||||||
package ak
|
package ak
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"goauthentik.io/internal/utils/sentry"
|
||||||
|
"goauthentik.io/internal/utils/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
MetricsSocketName = "authentik-metrics.sock"
|
||||||
OutpostInfo = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
OutpostInfo = promauto.NewGaugeVec(prometheus.GaugeOpts{
|
||||||
Name: "authentik_outpost_info",
|
Name: "authentik_outpost_info",
|
||||||
Help: "Outpost info",
|
Help: "Outpost info",
|
||||||
@@ -19,3 +29,43 @@ var (
|
|||||||
Help: "Connection status",
|
Help: "Connection status",
|
||||||
}, []string{"outpost_name", "outpost_type", "uuid"})
|
}, []string{"outpost_name", "outpost_type", "uuid"})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func MetricsRouter() *mux.Router {
|
||||||
|
m := mux.NewRouter()
|
||||||
|
m.Use(sentry.SentryNoSampleMiddleware)
|
||||||
|
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
rw.WriteHeader(204)
|
||||||
|
})
|
||||||
|
m.Path("/metrics").Handler(promhttp.Handler())
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunMetricsServer(listen string, router *mux.Router) {
|
||||||
|
l := log.WithField("logger", "authentik.outpost.metrics").WithField("listen", listen)
|
||||||
|
l.Info("Starting Metrics server")
|
||||||
|
err := http.ListenAndServe(listen, router)
|
||||||
|
if err != nil {
|
||||||
|
l.WithError(err).Warning("Failed to start metrics listener")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunMetricsUnix(router *mux.Router) {
|
||||||
|
socketPath := path.Join(os.TempDir(), MetricsSocketName)
|
||||||
|
l := log.WithField("logger", "authentik.outpost.metrics").WithField("listen", socketPath)
|
||||||
|
ln, err := unix.Listen(socketPath)
|
||||||
|
if err != nil {
|
||||||
|
l.WithError(err).Warning("failed to listen")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err := ln.Close()
|
||||||
|
if err != nil {
|
||||||
|
l.WithError(err).Warning("failed to close listener")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
l.WithField("listen", socketPath).Info("Starting Metrics server")
|
||||||
|
err = http.Serve(ln, router)
|
||||||
|
if err != nil {
|
||||||
|
l.WithError(err).Warning("Failed to start metrics listener")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"goauthentik.io/internal/config"
|
"goauthentik.io/internal/config"
|
||||||
"goauthentik.io/internal/crypto"
|
"goauthentik.io/internal/crypto"
|
||||||
"goauthentik.io/internal/outpost/ak"
|
"goauthentik.io/internal/outpost/ak"
|
||||||
"goauthentik.io/internal/outpost/ldap/metrics"
|
|
||||||
"goauthentik.io/internal/utils"
|
"goauthentik.io/internal/utils"
|
||||||
|
|
||||||
"beryju.io/ldap"
|
"beryju.io/ldap"
|
||||||
@@ -63,9 +62,7 @@ func (ls *LDAPServer) Type() string {
|
|||||||
return "ldap"
|
return "ldap"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ls *LDAPServer) StartLDAPServer() error {
|
func (ls *LDAPServer) StartLDAPServer(listen string) error {
|
||||||
listen := config.Get().Listen.LDAP
|
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", listen)
|
ln, err := net.Listen("tcp", listen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ls.log.WithField("listen", listen).WithError(err).Warning("Failed to listen (SSL)")
|
ls.log.WithField("listen", listen).WithError(err).Warning("Failed to listen (SSL)")
|
||||||
@@ -89,26 +86,40 @@ func (ls *LDAPServer) StartLDAPServer() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ls *LDAPServer) Start() error {
|
func (ls *LDAPServer) Start() error {
|
||||||
|
listenLdap := config.Get().Listen.LDAP
|
||||||
|
listenLdaps := config.Get().Listen.LDAPS
|
||||||
|
listenMetrics := config.Get().Listen.Metrics
|
||||||
|
metricsRouter := ak.MetricsRouter()
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(3)
|
wg.Add(len(listenLdap) + len(listenLdaps) + 1 + len(listenMetrics))
|
||||||
|
for _, listen := range listenLdap {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
metrics.RunServer()
|
err := ls.StartLDAPServer(listen)
|
||||||
}()
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
err := ls.StartLDAPServer()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
for _, listen := range listenLdaps {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
err := ls.StartLDAPTLSServer()
|
err := ls.StartLDAPTLSServer(listen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
ak.RunMetricsUnix(metricsRouter)
|
||||||
|
}()
|
||||||
|
for _, listen := range listenMetrics {
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
ak.RunMetricsServer(listen, metricsRouter)
|
||||||
|
}()
|
||||||
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/pires/go-proxyproto"
|
"github.com/pires/go-proxyproto"
|
||||||
"goauthentik.io/internal/config"
|
|
||||||
"goauthentik.io/internal/utils"
|
"goauthentik.io/internal/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,8 +36,7 @@ func (ls *LDAPServer) getCertificates(info *tls.ClientHelloInfo) (*tls.Certifica
|
|||||||
return ls.defaultCert, nil
|
return ls.defaultCert, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ls *LDAPServer) StartLDAPTLSServer() error {
|
func (ls *LDAPServer) StartLDAPTLSServer(listen string) error {
|
||||||
listen := config.Get().Listen.LDAPS
|
|
||||||
tlsConfig := utils.GetTLSConfig()
|
tlsConfig := utils.GetTLSConfig()
|
||||||
tlsConfig.GetCertificate = ls.getCertificates
|
tlsConfig.GetCertificate = ls.getCertificates
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,8 @@
|
|||||||
package metrics
|
package metrics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"goauthentik.io/internal/config"
|
|
||||||
"goauthentik.io/internal/utils/sentry"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -23,19 +15,3 @@ var (
|
|||||||
Help: "Total number of rejected requests",
|
Help: "Total number of rejected requests",
|
||||||
}, []string{"outpost_name", "type", "reason", "app"})
|
}, []string{"outpost_name", "type", "reason", "app"})
|
||||||
)
|
)
|
||||||
|
|
||||||
func RunServer() {
|
|
||||||
m := mux.NewRouter()
|
|
||||||
l := log.WithField("logger", "authentik.outpost.metrics")
|
|
||||||
m.Use(sentry.SentryNoSampleMiddleware)
|
|
||||||
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
rw.WriteHeader(204)
|
|
||||||
})
|
|
||||||
m.Path("/metrics").Handler(promhttp.Handler())
|
|
||||||
listen := config.Get().Listen.Metrics
|
|
||||||
l.WithField("listen", listen).Info("Starting Metrics server")
|
|
||||||
err := http.ListenAndServe(listen, m)
|
|
||||||
if err != nil {
|
|
||||||
l.WithError(err).Warning("Failed to start metrics listener")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,16 +1,8 @@
|
|||||||
package metrics
|
package metrics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"goauthentik.io/internal/config"
|
|
||||||
"goauthentik.io/internal/utils/sentry"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -23,19 +15,3 @@ var (
|
|||||||
Help: "Proxy upstream response latencies in seconds",
|
Help: "Proxy upstream response latencies in seconds",
|
||||||
}, []string{"outpost_name", "method", "scheme", "host", "upstream_host"})
|
}, []string{"outpost_name", "method", "scheme", "host", "upstream_host"})
|
||||||
)
|
)
|
||||||
|
|
||||||
func RunServer() {
|
|
||||||
m := mux.NewRouter()
|
|
||||||
l := log.WithField("logger", "authentik.outpost.metrics")
|
|
||||||
m.Use(sentry.SentryNoSampleMiddleware)
|
|
||||||
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
rw.WriteHeader(204)
|
|
||||||
})
|
|
||||||
m.Path("/metrics").Handler(promhttp.Handler())
|
|
||||||
listen := config.Get().Listen.Metrics
|
|
||||||
l.WithField("listen", listen).Info("Starting Metrics server")
|
|
||||||
err := http.ListenAndServe(listen, m)
|
|
||||||
if err != nil {
|
|
||||||
l.WithError(err).Warning("Failed to start metrics listener")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import (
|
|||||||
"goauthentik.io/internal/crypto"
|
"goauthentik.io/internal/crypto"
|
||||||
"goauthentik.io/internal/outpost/ak"
|
"goauthentik.io/internal/outpost/ak"
|
||||||
"goauthentik.io/internal/outpost/proxyv2/application"
|
"goauthentik.io/internal/outpost/proxyv2/application"
|
||||||
"goauthentik.io/internal/outpost/proxyv2/metrics"
|
|
||||||
"goauthentik.io/internal/utils"
|
"goauthentik.io/internal/utils"
|
||||||
sentryutils "goauthentik.io/internal/utils/sentry"
|
sentryutils "goauthentik.io/internal/utils/sentry"
|
||||||
"goauthentik.io/internal/utils/web"
|
"goauthentik.io/internal/utils/web"
|
||||||
@@ -127,11 +126,10 @@ func (ps *ProxyServer) getCertificates(info *tls.ClientHelloInfo) (*tls.Certific
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTP constructs a net.Listener and starts handling HTTP requests
|
// ServeHTTP constructs a net.Listener and starts handling HTTP requests
|
||||||
func (ps *ProxyServer) ServeHTTP() {
|
func (ps *ProxyServer) ServeHTTP(listen string) {
|
||||||
listenAddress := config.Get().Listen.HTTP
|
listener, err := net.Listen("tcp", listen)
|
||||||
listener, err := net.Listen("tcp", listenAddress)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ps.log.WithField("listen", listenAddress).WithError(err).Warning("Failed to listen")
|
ps.log.WithField("listen", listen).WithError(err).Warning("Failed to listen")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
proxyListener := &proxyproto.Listener{Listener: listener, ConnPolicy: utils.GetProxyConnectionPolicy()}
|
proxyListener := &proxyproto.Listener{Listener: listener, ConnPolicy: utils.GetProxyConnectionPolicy()}
|
||||||
@@ -142,18 +140,17 @@ func (ps *ProxyServer) ServeHTTP() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ps.log.WithField("listen", listenAddress).Info("Starting HTTP server")
|
ps.log.WithField("listen", listen).Info("Starting HTTP server")
|
||||||
ps.serve(proxyListener)
|
ps.serve(proxyListener)
|
||||||
ps.log.WithField("listen", listenAddress).Info("Stopping HTTP server")
|
ps.log.WithField("listen", listen).Info("Stopping HTTP server")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTPS constructs a net.Listener and starts handling HTTPS requests
|
// ServeHTTPS constructs a net.Listener and starts handling HTTPS requests
|
||||||
func (ps *ProxyServer) ServeHTTPS() {
|
func (ps *ProxyServer) ServeHTTPS(listen string) {
|
||||||
listenAddress := config.Get().Listen.HTTPS
|
|
||||||
tlsConfig := utils.GetTLSConfig()
|
tlsConfig := utils.GetTLSConfig()
|
||||||
tlsConfig.GetCertificate = ps.getCertificates
|
tlsConfig.GetCertificate = ps.getCertificates
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", listenAddress)
|
ln, err := net.Listen("tcp", listen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ps.log.WithError(err).Warning("Failed to listen (TLS)")
|
ps.log.WithError(err).Warning("Failed to listen (TLS)")
|
||||||
return
|
return
|
||||||
@@ -167,26 +164,40 @@ func (ps *ProxyServer) ServeHTTPS() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
tlsListener := tls.NewListener(proxyListener, tlsConfig)
|
tlsListener := tls.NewListener(proxyListener, tlsConfig)
|
||||||
ps.log.WithField("listen", listenAddress).Info("Starting HTTPS server")
|
ps.log.WithField("listen", listen).Info("Starting HTTPS server")
|
||||||
ps.serve(tlsListener)
|
ps.serve(tlsListener)
|
||||||
ps.log.WithField("listen", listenAddress).Info("Stopping HTTPS server")
|
ps.log.WithField("listen", listen).Info("Stopping HTTPS server")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ps *ProxyServer) Start() error {
|
func (ps *ProxyServer) Start() error {
|
||||||
|
listenHttp := config.Get().Listen.HTTP
|
||||||
|
listenHttps := config.Get().Listen.HTTPS
|
||||||
|
listenMetrics := config.Get().Listen.Metrics
|
||||||
|
metricsRouter := ak.MetricsRouter()
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(3)
|
wg.Add(len(listenHttp) + len(listenHttps) + 1 + len(listenMetrics))
|
||||||
|
for _, listen := range listenHttp {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
ps.ServeHTTP()
|
ps.ServeHTTP(listen)
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
for _, listen := range listenHttps {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
ps.ServeHTTPS()
|
ps.ServeHTTPS(listen)
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
metrics.RunServer()
|
ak.RunMetricsUnix(metricsRouter)
|
||||||
}()
|
}()
|
||||||
|
for _, listen := range listenMetrics {
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
ak.RunMetricsServer(listen, metricsRouter)
|
||||||
|
}()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
package metrics
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"goauthentik.io/internal/config"
|
|
||||||
"goauthentik.io/internal/utils/sentry"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func RunServer() {
|
|
||||||
m := mux.NewRouter()
|
|
||||||
l := log.WithField("logger", "authentik.outpost.metrics")
|
|
||||||
m.Use(sentry.SentryNoSampleMiddleware)
|
|
||||||
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
rw.WriteHeader(204)
|
|
||||||
})
|
|
||||||
m.Path("/metrics").Handler(promhttp.Handler())
|
|
||||||
listen := config.Get().Listen.Metrics
|
|
||||||
l.WithField("listen", listen).Info("Starting Metrics server")
|
|
||||||
err := http.ListenAndServe(listen, m)
|
|
||||||
if err != nil {
|
|
||||||
l.WithError(err).Warning("Failed to start metrics listener")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,9 +9,9 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/wwt/guac"
|
"github.com/wwt/guac"
|
||||||
|
|
||||||
|
"goauthentik.io/internal/config"
|
||||||
"goauthentik.io/internal/outpost/ak"
|
"goauthentik.io/internal/outpost/ak"
|
||||||
"goauthentik.io/internal/outpost/rac/connection"
|
"goauthentik.io/internal/outpost/rac/connection"
|
||||||
"goauthentik.io/internal/outpost/rac/metrics"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RACServer struct {
|
type RACServer struct {
|
||||||
@@ -92,12 +92,10 @@ func (rs *RACServer) wsHandler(ctx context.Context, msg ak.Event) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RACServer) Start() error {
|
func (rs *RACServer) Start() error {
|
||||||
|
listenMetrics := config.Get().Listen.Metrics
|
||||||
|
metricsRouter := ak.MetricsRouter()
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(2)
|
wg.Add(1 + 1 + len(listenMetrics))
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
metrics.RunServer()
|
|
||||||
}()
|
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
err := rs.startGuac()
|
err := rs.startGuac()
|
||||||
@@ -105,6 +103,16 @@ func (rs *RACServer) Start() error {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
ak.RunMetricsUnix(metricsRouter)
|
||||||
|
}()
|
||||||
|
for _, listen := range listenMetrics {
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
ak.RunMetricsServer(listen, metricsRouter)
|
||||||
|
}()
|
||||||
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,8 @@
|
|||||||
package metrics
|
package metrics
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"goauthentik.io/internal/config"
|
|
||||||
"goauthentik.io/internal/utils/sentry"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -23,19 +15,3 @@ var (
|
|||||||
Help: "Total number of rejected requests",
|
Help: "Total number of rejected requests",
|
||||||
}, []string{"outpost_name", "reason", "app"})
|
}, []string{"outpost_name", "reason", "app"})
|
||||||
)
|
)
|
||||||
|
|
||||||
func RunServer() {
|
|
||||||
m := mux.NewRouter()
|
|
||||||
l := log.WithField("logger", "authentik.outpost.metrics")
|
|
||||||
m.Use(sentry.SentryNoSampleMiddleware)
|
|
||||||
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
rw.WriteHeader(204)
|
|
||||||
})
|
|
||||||
m.Path("/metrics").Handler(promhttp.Handler())
|
|
||||||
listen := config.Get().Listen.Metrics
|
|
||||||
l.WithField("listen", listen).Info("Starting Metrics server")
|
|
||||||
err := http.ListenAndServe(listen, m)
|
|
||||||
if err != nil {
|
|
||||||
l.WithError(err).Warning("Failed to start metrics listener")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"goauthentik.io/internal/config"
|
"goauthentik.io/internal/config"
|
||||||
"goauthentik.io/internal/outpost/ak"
|
"goauthentik.io/internal/outpost/ak"
|
||||||
"goauthentik.io/internal/outpost/radius/metrics"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"layeh.com/radius"
|
"layeh.com/radius"
|
||||||
)
|
)
|
||||||
@@ -30,7 +30,7 @@ type ProviderInstance struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RadiusServer struct {
|
type RadiusServer struct {
|
||||||
s radius.PacketServer
|
s []*radius.PacketServer
|
||||||
log *log.Entry
|
log *log.Entry
|
||||||
ac *ak.APIController
|
ac *ak.APIController
|
||||||
cryptoStore *ak.CryptoStore
|
cryptoStore *ak.CryptoStore
|
||||||
@@ -45,10 +45,13 @@ func NewServer(ac *ak.APIController) ak.Outpost {
|
|||||||
providers: map[int32]*ProviderInstance{},
|
providers: map[int32]*ProviderInstance{},
|
||||||
cryptoStore: ak.NewCryptoStore(ac.Client.CryptoAPI),
|
cryptoStore: ak.NewCryptoStore(ac.Client.CryptoAPI),
|
||||||
}
|
}
|
||||||
rs.s = radius.PacketServer{
|
listenRadius := config.Get().Listen.Radius
|
||||||
|
for _, listen := range listenRadius {
|
||||||
|
rs.s = append(rs.s, &radius.PacketServer{
|
||||||
Handler: rs,
|
Handler: rs,
|
||||||
SecretSource: rs,
|
SecretSource: rs,
|
||||||
Addr: config.Get().Listen.Radius,
|
Addr: listen,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return rs
|
return rs
|
||||||
}
|
}
|
||||||
@@ -95,29 +98,44 @@ func (rs *RadiusServer) RADIUSSecret(ctx context.Context, remoteAddr net.Addr) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RadiusServer) Start() error {
|
func (rs *RadiusServer) Start() error {
|
||||||
|
listenMetrics := config.Get().Listen.Metrics
|
||||||
|
metricsRouter := ak.MetricsRouter()
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(2)
|
wg.Add(len(rs.s) + 1 + len(listenMetrics))
|
||||||
|
for _, s := range rs.s {
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
metrics.RunServer()
|
rs.log.WithField("listen", s.Addr).Info("Starting radius server")
|
||||||
}()
|
err := s.ListenAndServe()
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
rs.log.WithField("listen", rs.s.Addr).Info("Starting radius server")
|
|
||||||
err := rs.s.ListenAndServe()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
ak.RunMetricsUnix(metricsRouter)
|
||||||
|
}()
|
||||||
|
for _, listen := range listenMetrics {
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
ak.RunMetricsServer(listen, metricsRouter)
|
||||||
|
}()
|
||||||
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RadiusServer) Stop() error {
|
func (rs *RadiusServer) Stop() error {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
err := rs.s.Shutdown(ctx)
|
errs := new(errgroup.Group)
|
||||||
|
for _, s := range rs.s {
|
||||||
|
errs.Go(func() error {
|
||||||
|
return s.Shutdown(ctx)
|
||||||
|
})
|
||||||
|
}
|
||||||
cancel()
|
cancel()
|
||||||
return err
|
return errs.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RadiusServer) TimerFlowCacheExpiry(context.Context) {}
|
func (rs *RadiusServer) TimerFlowCacheExpiry(context.Context) {}
|
||||||
|
|||||||
43
internal/utils/unix/unix.go
Normal file
43
internal/utils/unix/unix.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package unix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Listener struct {
|
||||||
|
*net.UnixListener
|
||||||
|
}
|
||||||
|
|
||||||
|
type Conn struct {
|
||||||
|
net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func Listen(path string) (*Listener, error) {
|
||||||
|
addr, err := net.ResolveUnixAddr("unix", path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ln, err := net.ListenUnix("unix", addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Listener{
|
||||||
|
ln,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Listener) Accept() (net.Conn, error) {
|
||||||
|
c, err := l.UnixListener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Conn{c}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) LocalAddr() net.Addr {
|
||||||
|
return &net.TCPAddr{IP: net.IPv6loopback, Port: 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) RemoteAddr() net.Addr {
|
||||||
|
return &net.TCPAddr{IP: net.IPv6loopback, Port: 0}
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ var Requests = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
|||||||
Help: "API request latencies in seconds",
|
Help: "API request latencies in seconds",
|
||||||
}, []string{"dest"})
|
}, []string{"dest"})
|
||||||
|
|
||||||
func (ws *WebServer) runMetricsServer() {
|
func (ws *WebServer) runMetricsServer(listen string) {
|
||||||
l := log.WithField("logger", "authentik.router.metrics")
|
l := log.WithField("logger", "authentik.router.metrics")
|
||||||
|
|
||||||
m := mux.NewRouter()
|
m := mux.NewRouter()
|
||||||
@@ -49,10 +49,10 @@ func (ws *WebServer) runMetricsServer() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
l.WithField("listen", config.Get().Listen.Metrics).Info("Starting Metrics server")
|
l.WithField("listen", listen).Info("Starting Metrics server")
|
||||||
err := http.ListenAndServe(config.Get().Listen.Metrics, m)
|
err := http.ListenAndServe(listen, m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.WithError(err).Warning("Failed to start metrics server")
|
l.WithError(err).Warning("Failed to start metrics server")
|
||||||
}
|
}
|
||||||
l.WithField("listen", config.Get().Listen.Metrics).Info("Stopping Metrics server")
|
l.WithField("listen", listen).Info("Stopping Metrics server")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,17 +21,18 @@ import (
|
|||||||
"goauthentik.io/internal/config"
|
"goauthentik.io/internal/config"
|
||||||
"goauthentik.io/internal/constants"
|
"goauthentik.io/internal/constants"
|
||||||
"goauthentik.io/internal/gounicorn"
|
"goauthentik.io/internal/gounicorn"
|
||||||
"goauthentik.io/internal/outpost/ak"
|
|
||||||
"goauthentik.io/internal/outpost/proxyv2"
|
"goauthentik.io/internal/outpost/proxyv2"
|
||||||
"goauthentik.io/internal/utils"
|
"goauthentik.io/internal/utils"
|
||||||
|
"goauthentik.io/internal/utils/unix"
|
||||||
"goauthentik.io/internal/utils/web"
|
"goauthentik.io/internal/utils/web"
|
||||||
"goauthentik.io/internal/web/brand_tls"
|
"goauthentik.io/internal/web/brand_tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
SocketName = "authentik.sock"
|
||||||
IPCKeyFile = "authentik-core-ipc.key"
|
IPCKeyFile = "authentik-core-ipc.key"
|
||||||
MetricsKeyFile = "authentik-core-metrics.key"
|
MetricsKeyFile = "authentik-core-metrics.key"
|
||||||
UnixSocketName = "authentik-core.sock"
|
CoreSocketName = "authentik-core.sock"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WebServer struct {
|
type WebServer struct {
|
||||||
@@ -64,7 +65,7 @@ func NewWebServer() *WebServer {
|
|||||||
loggingHandler.Use(web.NewLoggingHandler(l, nil))
|
loggingHandler.Use(web.NewLoggingHandler(l, nil))
|
||||||
|
|
||||||
tmp := os.TempDir()
|
tmp := os.TempDir()
|
||||||
socketPath := path.Join(tmp, UnixSocketName)
|
socketPath := path.Join(tmp, CoreSocketName)
|
||||||
|
|
||||||
// create http client to talk to backend, normal client if we're in debug more
|
// create http client to talk to backend, normal client if we're in debug more
|
||||||
// and a client that connects to our socket when in non debug mode
|
// and a client that connects to our socket when in non debug mode
|
||||||
@@ -140,7 +141,8 @@ func (ws *WebServer) prepareKeys() {
|
|||||||
func (ws *WebServer) Start() {
|
func (ws *WebServer) Start() {
|
||||||
ws.prepareKeys()
|
ws.prepareKeys()
|
||||||
|
|
||||||
u, err := url.Parse(fmt.Sprintf("http://%s%s", config.Get().Listen.HTTP, config.Get().Web.Path))
|
socketPath := path.Join(os.TempDir(), SocketName)
|
||||||
|
u, err := url.Parse(fmt.Sprintf("http://localhost%s", config.Get().Web.Path))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -150,7 +152,11 @@ func (ws *WebServer) Start() {
|
|||||||
apiConfig.HTTPClient = &http.Client{
|
apiConfig.HTTPClient = &http.Client{
|
||||||
Transport: web.NewUserAgentTransport(
|
Transport: web.NewUserAgentTransport(
|
||||||
constants.UserAgentIPC(),
|
constants.UserAgentIPC(),
|
||||||
ak.GetTLSTransport(),
|
&http.Transport{
|
||||||
|
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||||
|
return net.Dial("unix", socketPath)
|
||||||
|
},
|
||||||
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
apiConfig.Servers = api.ServerConfigurations{
|
apiConfig.Servers = api.ServerConfigurations{
|
||||||
@@ -171,10 +177,18 @@ func (ws *WebServer) Start() {
|
|||||||
go tw.Start()
|
go tw.Start()
|
||||||
})
|
})
|
||||||
|
|
||||||
go ws.runMetricsServer()
|
for _, listen := range config.Get().Listen.Metrics {
|
||||||
|
go ws.runMetricsServer(listen)
|
||||||
|
}
|
||||||
go ws.attemptStartBackend()
|
go ws.attemptStartBackend()
|
||||||
go ws.listenPlain()
|
_ = os.Remove(socketPath)
|
||||||
go ws.listenTLS()
|
go ws.listenUnix(socketPath)
|
||||||
|
for _, listen := range config.Get().Listen.HTTP {
|
||||||
|
go ws.listenPlain(listen)
|
||||||
|
}
|
||||||
|
for _, listen := range config.Get().Listen.HTTPS {
|
||||||
|
go ws.listenTLS(listen)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WebServer) attemptStartBackend() {
|
func (ws *WebServer) attemptStartBackend() {
|
||||||
@@ -225,23 +239,41 @@ func (ws *WebServer) Shutdown() {
|
|||||||
ws.stop <- struct{}{}
|
ws.stop <- struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WebServer) listenPlain() {
|
func (ws *WebServer) listenUnix(listen string) {
|
||||||
ln, err := net.Listen("tcp", config.Get().Listen.HTTP)
|
ln, err := unix.Listen(listen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ws.log.WithError(err).Warning("failed to listen")
|
ws.log.WithField("listen", listen).WithError(err).Warning("failed to listen")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err := ln.Close()
|
||||||
|
if err != nil {
|
||||||
|
ws.log.WithField("listen", listen).WithError(err).Warning("failed to close listener")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
ws.log.WithField("listen", listen).Info("Starting HTTP server")
|
||||||
|
ws.serve(ln)
|
||||||
|
ws.log.WithField("listen", listen).Info("Stopping HTTP server")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WebServer) listenPlain(listen string) {
|
||||||
|
ln, err := net.Listen("tcp", listen)
|
||||||
|
if err != nil {
|
||||||
|
ws.log.WithField("listen", listen).WithError(err).Warning("failed to listen")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
proxyListener := &proxyproto.Listener{Listener: ln, ConnPolicy: utils.GetProxyConnectionPolicy()}
|
proxyListener := &proxyproto.Listener{Listener: ln, ConnPolicy: utils.GetProxyConnectionPolicy()}
|
||||||
defer func() {
|
defer func() {
|
||||||
err := proxyListener.Close()
|
err := proxyListener.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ws.log.WithError(err).Warning("failed to close proxy listener")
|
ws.log.WithField("listen", listen).WithError(err).Warning("failed to close proxy listener")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
ws.log.WithField("listen", config.Get().Listen.HTTP).Info("Starting HTTP server")
|
ws.log.WithField("listen", listen).Info("Starting HTTP server")
|
||||||
ws.serve(proxyListener)
|
ws.serve(proxyListener)
|
||||||
ws.log.WithField("listen", config.Get().Listen.HTTP).Info("Stopping HTTP server")
|
ws.log.WithField("listen", listen).Info("Stopping HTTP server")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ws *WebServer) serve(listener net.Listener) {
|
func (ws *WebServer) serve(listener net.Listener) {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/pires/go-proxyproto"
|
"github.com/pires/go-proxyproto"
|
||||||
|
|
||||||
"goauthentik.io/internal/config"
|
|
||||||
"goauthentik.io/internal/crypto"
|
"goauthentik.io/internal/crypto"
|
||||||
"goauthentik.io/internal/utils"
|
"goauthentik.io/internal/utils"
|
||||||
"goauthentik.io/internal/utils/web"
|
"goauthentik.io/internal/utils/web"
|
||||||
@@ -48,13 +47,13 @@ func (ws *WebServer) GetCertificate() func(ch *tls.ClientHelloInfo) (*tls.Config
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTPS constructs a net.Listener and starts handling HTTPS requests
|
// ServeHTTPS constructs a net.Listener and starts handling HTTPS requests
|
||||||
func (ws *WebServer) listenTLS() {
|
func (ws *WebServer) listenTLS(listen string) {
|
||||||
tlsConfig := utils.GetTLSConfig()
|
tlsConfig := utils.GetTLSConfig()
|
||||||
tlsConfig.GetConfigForClient = ws.GetCertificate()
|
tlsConfig.GetConfigForClient = ws.GetCertificate()
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", config.Get().Listen.HTTPS)
|
ln, err := net.Listen("tcp", listen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ws.log.WithError(err).Warning("failed to listen (TLS)")
|
ws.log.WithField("listen", listen).WithError(err).Warning("failed to listen (TLS)")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
proxyListener := &proxyproto.Listener{
|
proxyListener := &proxyproto.Listener{
|
||||||
@@ -71,7 +70,7 @@ func (ws *WebServer) listenTLS() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
tlsListener := tls.NewListener(proxyListener, tlsConfig)
|
tlsListener := tls.NewListener(proxyListener, tlsConfig)
|
||||||
ws.log.WithField("listen", config.Get().Listen.HTTPS).Info("Starting HTTPS server")
|
ws.log.WithField("listen", listen).Info("Starting HTTPS server")
|
||||||
ws.serve(tlsListener)
|
ws.serve(tlsListener)
|
||||||
ws.log.WithField("listen", config.Get().Listen.HTTPS).Info("Stopping HTTPS server")
|
ws.log.WithField("listen", listen).Info("Stopping HTTPS server")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,43 +237,43 @@ Defaults to `seconds=60`.
|
|||||||
|
|
||||||
##### `AUTHENTIK_LISTEN__HTTP`
|
##### `AUTHENTIK_LISTEN__HTTP`
|
||||||
|
|
||||||
Listening address:port for HTTP.
|
List of comma-separated `address:port` values for HTTP.
|
||||||
|
|
||||||
Applies to the Server, the Worker, and Proxy outposts.
|
Applies to the Server, the Worker, and Proxy outposts.
|
||||||
|
|
||||||
Defaults to `0.0.0.0:9000`.
|
Defaults to `[::]:9000`.
|
||||||
|
|
||||||
##### `AUTHENTIK_LISTEN__HTTPS`
|
##### `AUTHENTIK_LISTEN__HTTPS`
|
||||||
|
|
||||||
Listening address:port for HTTPS.
|
List of comma-separated `address:port` values for HTTPS.
|
||||||
|
|
||||||
Applies to the Server and Proxy outposts.
|
Applies to the Server and Proxy outposts.
|
||||||
|
|
||||||
Defaults to `0.0.0.0:9443`.
|
Defaults to `[::]:9443`.
|
||||||
|
|
||||||
##### `AUTHENTIK_LISTEN__LDAP`
|
##### `AUTHENTIK_LISTEN__LDAP`
|
||||||
|
|
||||||
Listening address:port for LDAP.
|
List of comma-separated `address:port` values for LDAP.
|
||||||
|
|
||||||
Applies to LDAP outposts.
|
Applies to LDAP outposts.
|
||||||
|
|
||||||
Defaults to `0.0.0.0:3389`.
|
Defaults to `[::]:3389`.
|
||||||
|
|
||||||
##### `AUTHENTIK_LISTEN__LDAPS`
|
##### `AUTHENTIK_LISTEN__LDAPS`
|
||||||
|
|
||||||
Listening address:port for LDAPS.
|
List of comma-separated `address:port` values for LDAPS.
|
||||||
|
|
||||||
Applies to LDAP outposts.
|
Applies to LDAP outposts.
|
||||||
|
|
||||||
Defaults to `0.0.0.0:6636`.
|
Defaults to `[::]:6636`.
|
||||||
|
|
||||||
##### `AUTHENTIK_LISTEN__METRICS`
|
##### `AUTHENTIK_LISTEN__METRICS`
|
||||||
|
|
||||||
Listening address:port for Prometheus metrics.
|
List of comma-separated `address:port` values for Prometheus metrics.
|
||||||
|
|
||||||
Applies to all.
|
Applies to all.
|
||||||
|
|
||||||
Defaults to `0.0.0.0:9300`.
|
Defaults to `[::]:9300`.
|
||||||
|
|
||||||
##### `AUTHENTIK_LISTEN__DEBUG`
|
##### `AUTHENTIK_LISTEN__DEBUG`
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ draft: true
|
|||||||
|
|
||||||
## Highlights
|
## Highlights
|
||||||
|
|
||||||
<!-- ## Breaking changes -->
|
## Breaking changes
|
||||||
|
|
||||||
|
### Listening on multiple IPs
|
||||||
|
|
||||||
|
For advanced use cases, authentik now supports setting listening settings to a comma-separated list of IPs. With this change, the default IP we listen on changed from `0.0.0.0` to `[::]` to better match ecosystem standards. Some IPv4-only environments might need to adapt those settings.
|
||||||
|
|
||||||
## New features and improvements
|
## New features and improvements
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user