providers/proxy: add caddy endpoint (#3330)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		| @ -13,12 +13,14 @@ import ( | ||||
|  | ||||
| const ( | ||||
| 	envoyPrefix   = "/outpost.goauthentik.io/auth/envoy" | ||||
| 	caddyPrefix   = "/outpost.goauthentik.io/auth/caddy" | ||||
| 	traefikPrefix = "/outpost.goauthentik.io/auth/traefik" | ||||
| 	nginxPrefix   = "/outpost.goauthentik.io/auth/nginx" | ||||
| ) | ||||
|  | ||||
| func (a *Application) configureForward() error { | ||||
| 	a.mux.HandleFunc(traefikPrefix, a.forwardHandleTraefik) | ||||
| 	a.mux.HandleFunc(caddyPrefix, a.forwardHandleCaddy) | ||||
| 	a.mux.HandleFunc(nginxPrefix, a.forwardHandleNginx) | ||||
| 	a.mux.PathPrefix(envoyPrefix).HandlerFunc(a.forwardHandleEnvoy) | ||||
| 	return nil | ||||
| @ -87,6 +89,69 @@ func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Reque | ||||
| 	http.Redirect(rw, r, rdFinal, http.StatusTemporaryRedirect) | ||||
| } | ||||
|  | ||||
| func (a *Application) forwardHandleCaddy(rw http.ResponseWriter, r *http.Request) { | ||||
| 	a.log.WithField("header", r.Header).Trace("tracing headers for debug") | ||||
| 	// First check if we've got everything we need | ||||
| 	fwd, err := a.getTraefikForwardUrl(r) | ||||
| 	if err != nil { | ||||
| 		a.ReportMisconfiguration(r, fmt.Sprintf("Outpost %s (Provider %s) failed to detect a forward URL from Caddy", a.outpostName, a.proxyConfig.Name), map[string]interface{}{ | ||||
| 			"provider": a.proxyConfig.Name, | ||||
| 			"outpost":  a.outpostName, | ||||
| 			"url":      r.URL.String(), | ||||
| 			"headers":  cleanseHeaders(r.Header), | ||||
| 		}) | ||||
| 		http.Error(rw, "configuration error", http.StatusInternalServerError) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	claims, err := a.getClaims(r) | ||||
| 	if claims != nil && err == nil { | ||||
| 		a.addHeaders(rw.Header(), claims) | ||||
| 		rw.Header().Set("User-Agent", r.Header.Get("User-Agent")) | ||||
| 		a.log.WithField("headers", rw.Header()).Trace("headers written to forward_auth") | ||||
| 		return | ||||
| 	} else if claims == nil && a.IsAllowlisted(fwd) { | ||||
| 		a.log.Trace("path can be accessed without authentication") | ||||
| 		return | ||||
| 	} | ||||
| 	if strings.HasPrefix(r.Header.Get("X-Forwarded-Uri"), "/outpost.goauthentik.io") { | ||||
| 		a.log.WithField("url", r.URL.String()).Trace("path begins with /outpost.goauthentik.io, allowing access") | ||||
| 		return | ||||
| 	} | ||||
| 	host := "" | ||||
| 	// Optional suffix, which is appended to the URL | ||||
| 	if *a.proxyConfig.Mode.Get() == api.PROXYMODE_FORWARD_SINGLE { | ||||
| 		host = web.GetHost(r) | ||||
| 	} else if *a.proxyConfig.Mode.Get() == api.PROXYMODE_FORWARD_DOMAIN { | ||||
| 		eh, err := url.Parse(a.proxyConfig.ExternalHost) | ||||
| 		if err != nil { | ||||
| 			a.log.WithField("host", a.proxyConfig.ExternalHost).WithError(err).Warning("invalid external_host") | ||||
| 		} else { | ||||
| 			host = eh.Host | ||||
| 		} | ||||
| 	} | ||||
| 	// set the redirect flag to the current URL we have, since we redirect | ||||
| 	// to a (possibly) different domain, but we want to be redirected back | ||||
| 	// to the application | ||||
| 	// X-Forwarded-Uri is only the path, so we need to build the entire URL | ||||
| 	s, _ := a.sessions.Get(r, constants.SessionName) | ||||
| 	if _, redirectSet := s.Values[constants.SessionRedirect]; !redirectSet { | ||||
| 		s.Values[constants.SessionRedirect] = fwd.String() | ||||
| 		err = s.Save(r, rw) | ||||
| 		if err != nil { | ||||
| 			a.log.WithError(err).Warning("failed to save session before redirect") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	proto := r.Header.Get("X-Forwarded-Proto") | ||||
| 	if proto != "" { | ||||
| 		proto = proto + ":" | ||||
| 	} | ||||
| 	rdFinal := fmt.Sprintf("%s//%s%s", proto, host, "/outpost.goauthentik.io/start") | ||||
| 	a.log.WithField("url", rdFinal).Debug("Redirecting to login") | ||||
| 	http.Redirect(rw, r, rdFinal, http.StatusTemporaryRedirect) | ||||
| } | ||||
|  | ||||
| func (a *Application) forwardHandleNginx(rw http.ResponseWriter, r *http.Request) { | ||||
| 	a.log.WithField("header", r.Header).Trace("tracing headers for debug") | ||||
| 	fwd, err := a.getNginxForwardUrl(r) | ||||
|  | ||||
							
								
								
									
										132
									
								
								internal/outpost/proxyv2/application/mode_forward_caddy_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								internal/outpost/proxyv2/application/mode_forward_caddy_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,132 @@ | ||||
| package application | ||||
|  | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"net/http/httptest" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 	"goauthentik.io/api/v3" | ||||
| 	"goauthentik.io/internal/outpost/proxyv2/constants" | ||||
| ) | ||||
|  | ||||
| func TestForwardHandleCaddy_Single_Blank(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/caddy", nil) | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.forwardHandleCaddy(rr, req) | ||||
|  | ||||
| 	assert.Equal(t, http.StatusInternalServerError, rr.Code) | ||||
| } | ||||
|  | ||||
| func TestForwardHandleCaddy_Single_Skip(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/caddy", nil) | ||||
| 	req.Header.Set("X-Forwarded-Proto", "http") | ||||
| 	req.Header.Set("X-Forwarded-Host", "test.goauthentik.io") | ||||
| 	req.Header.Set("X-Forwarded-Uri", "/skip") | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.forwardHandleCaddy(rr, req) | ||||
|  | ||||
| 	assert.Equal(t, http.StatusOK, rr.Code) | ||||
| } | ||||
|  | ||||
| func TestForwardHandleCaddy_Single_Headers(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/caddy", nil) | ||||
| 	req.Header.Set("X-Forwarded-Proto", "http") | ||||
| 	req.Header.Set("X-Forwarded-Host", "test.goauthentik.io") | ||||
| 	req.Header.Set("X-Forwarded-Uri", "/app") | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.forwardHandleCaddy(rr, req) | ||||
|  | ||||
| 	assert.Equal(t, rr.Code, http.StatusTemporaryRedirect) | ||||
| 	loc, _ := rr.Result().Location() | ||||
| 	assert.Equal(t, loc.String(), "http://test.goauthentik.io/outpost.goauthentik.io/start") | ||||
|  | ||||
| 	s, _ := a.sessions.Get(req, constants.SessionName) | ||||
| 	assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) | ||||
| } | ||||
|  | ||||
| func TestForwardHandleCaddy_Single_Claims(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/caddy", nil) | ||||
| 	req.Header.Set("X-Forwarded-Proto", "http") | ||||
| 	req.Header.Set("X-Forwarded-Host", "test.goauthentik.io") | ||||
| 	req.Header.Set("X-Forwarded-Uri", "/app") | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.forwardHandleCaddy(rr, req) | ||||
|  | ||||
| 	s, _ := a.sessions.Get(req, constants.SessionName) | ||||
| 	s.Values[constants.SessionClaims] = Claims{ | ||||
| 		Sub: "foo", | ||||
| 		Proxy: &ProxyClaims{ | ||||
| 			UserAttributes: map[string]interface{}{ | ||||
| 				"username": "foo", | ||||
| 				"password": "bar", | ||||
| 				"additionalHeaders": map[string]interface{}{ | ||||
| 					"foo": "bar", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	err := a.sessions.Save(req, rr, s) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
|  | ||||
| 	rr = httptest.NewRecorder() | ||||
| 	a.forwardHandleCaddy(rr, req) | ||||
|  | ||||
| 	h := rr.Result().Header | ||||
|  | ||||
| 	assert.Equal(t, []string{"Basic Zm9vOmJhcg=="}, h["Authorization"]) | ||||
| 	assert.Equal(t, []string{"bar"}, h["Foo"]) | ||||
| 	assert.Equal(t, []string{""}, h["User-Agent"]) | ||||
| 	assert.Equal(t, []string{""}, h["X-Authentik-Email"]) | ||||
| 	assert.Equal(t, []string{""}, h["X-Authentik-Groups"]) | ||||
| 	assert.Equal(t, []string{""}, h["X-Authentik-Jwt"]) | ||||
| 	assert.Equal(t, []string{""}, h["X-Authentik-Meta-App"]) | ||||
| 	assert.Equal(t, []string{""}, h["X-Authentik-Meta-Jwks"]) | ||||
| 	assert.Equal(t, []string{""}, h["X-Authentik-Meta-Outpost"]) | ||||
| 	assert.Equal(t, []string{""}, h["X-Authentik-Name"]) | ||||
| 	assert.Equal(t, []string{"foo"}, h["X-Authentik-Uid"]) | ||||
| 	assert.Equal(t, []string{""}, h["X-Authentik-Username"]) | ||||
| } | ||||
|  | ||||
| func TestForwardHandleCaddy_Domain_Blank(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	a.proxyConfig.Mode = *api.NewNullableProxyMode(api.PROXYMODE_FORWARD_DOMAIN.Ptr()) | ||||
| 	a.proxyConfig.CookieDomain = api.PtrString("foo") | ||||
| 	req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/caddy", nil) | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.forwardHandleCaddy(rr, req) | ||||
|  | ||||
| 	assert.Equal(t, http.StatusInternalServerError, rr.Code) | ||||
| } | ||||
|  | ||||
| func TestForwardHandleCaddy_Domain_Header(t *testing.T) { | ||||
| 	a := newTestApplication() | ||||
| 	a.proxyConfig.Mode = *api.NewNullableProxyMode(api.PROXYMODE_FORWARD_DOMAIN.Ptr()) | ||||
| 	a.proxyConfig.CookieDomain = api.PtrString("foo") | ||||
| 	a.proxyConfig.ExternalHost = "http://auth.test.goauthentik.io" | ||||
| 	req, _ := http.NewRequest("GET", "/outpost.goauthentik.io/auth/caddy", nil) | ||||
| 	req.Header.Set("X-Forwarded-Proto", "http") | ||||
| 	req.Header.Set("X-Forwarded-Host", "test.goauthentik.io") | ||||
| 	req.Header.Set("X-Forwarded-Uri", "/app") | ||||
|  | ||||
| 	rr := httptest.NewRecorder() | ||||
| 	a.forwardHandleCaddy(rr, req) | ||||
|  | ||||
| 	assert.Equal(t, http.StatusTemporaryRedirect, rr.Code) | ||||
| 	loc, _ := rr.Result().Location() | ||||
| 	assert.Equal(t, "http://auth.test.goauthentik.io/outpost.goauthentik.io/start", loc.String()) | ||||
|  | ||||
| 	s, _ := a.sessions.Get(req, constants.SessionName) | ||||
| 	assert.Equal(t, "http://test.goauthentik.io/app", s.Values[constants.SessionRedirect]) | ||||
| } | ||||
| @ -809,6 +809,10 @@ msgstr "Gecachte Richtlinien" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "Gecachte Abfrage, der Oupost hält alle Benutzer und Gruppen im Speicher und aktualisiert sich alle 5 Minuten." | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "Callback URL" | ||||
| @ -4403,6 +4407,7 @@ msgid "Redirect binding" | ||||
| msgstr "Bindings umleiten" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "Aktualisieren" | ||||
|  | ||||
|  | ||||
| @ -806,6 +806,10 @@ msgstr "Cached policies" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "Caddy (Standalone)" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "Callback URL" | ||||
| @ -4475,6 +4479,7 @@ msgid "Redirect binding" | ||||
| msgstr "Redirect binding" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "Refresh" | ||||
|  | ||||
|  | ||||
| @ -799,6 +799,10 @@ msgstr "Políticas almacenadas en caché" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "Al realizar consultas en caché, el puesto de avanzada mantiene a todos los usuarios y grupos en memoria y se actualizará cada 5 minutos." | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "URL de devolución de llamada" | ||||
| @ -4396,6 +4400,7 @@ msgid "Redirect binding" | ||||
| msgstr "Enlace de redirección" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "Actualizar" | ||||
|  | ||||
|  | ||||
| @ -805,6 +805,10 @@ msgstr "Politiques mises en cache" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "URL de rappel" | ||||
| @ -4438,6 +4442,7 @@ msgid "Redirect binding" | ||||
| msgstr "Redirection" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "Rafraîchir" | ||||
|  | ||||
|  | ||||
| @ -796,6 +796,10 @@ msgstr "Zasady w pamięci podręcznej" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "Zbuforowane zapytania, placówka przechowuje w pamięci wszystkich użytkowników i grupy i odświeża się co 5 minut." | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "URL wywołania zwrotnego" | ||||
| @ -4393,6 +4397,7 @@ msgid "Redirect binding" | ||||
| msgstr "Wiązanie przekierowania" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "Odśwież" | ||||
|  | ||||
|  | ||||
| @ -798,6 +798,10 @@ msgstr "" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "" | ||||
| @ -4455,6 +4459,7 @@ msgid "Redirect binding" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "" | ||||
|  | ||||
|  | ||||
| @ -799,6 +799,10 @@ msgstr "Önbelleğe alınan ilkeler" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "Önbelleğe alınmış sorgulama, üs tüm kullanıcıları ve grupları bellek içinde tutar ve her 5 Dakikada yenileyecektir." | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "Geri arama URL'si" | ||||
| @ -4398,6 +4402,7 @@ msgid "Redirect binding" | ||||
| msgstr "Yeniden yönlendirme bağlama" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "Yenile" | ||||
|  | ||||
|  | ||||
| @ -794,6 +794,10 @@ msgstr "缓存策略" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "缓存查询,前哨将所有用户和组保存在内存中,并每 5 分钟刷新一次。" | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "回调 URL" | ||||
| @ -4368,6 +4372,7 @@ msgid "Redirect binding" | ||||
| msgstr "重定向绑定" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "刷新" | ||||
|  | ||||
|  | ||||
| @ -796,6 +796,10 @@ msgstr "缓存策略" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "缓存查询,前哨将所有用户和组保存在内存中,并将每5分钟刷新一次。" | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "回调 URL" | ||||
| @ -4374,6 +4378,7 @@ msgid "Redirect binding" | ||||
| msgstr "重定向绑定" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "刷新" | ||||
|  | ||||
|  | ||||
| @ -796,6 +796,10 @@ msgstr "缓存策略" | ||||
| msgid "Cached querying, the outpost holds all users and groups in-memory and will refresh every 5 Minutes." | ||||
| msgstr "缓存查询,前哨将所有用户和组保存在内存中,并将每5分钟刷新一次。" | ||||
|  | ||||
| #: src/pages/providers/proxy/ProxyProviderViewPage.ts | ||||
| msgid "Caddy (Standalone)" | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/sources/oauth/OAuthSourceViewPage.ts | ||||
| msgid "Callback URL" | ||||
| msgstr "回调 URL" | ||||
| @ -4374,6 +4378,7 @@ msgid "Redirect binding" | ||||
| msgstr "重定向绑定" | ||||
|  | ||||
| #: src/elements/table/Table.ts | ||||
| #: src/elements/user/UserDevicesList.ts | ||||
| msgid "Refresh" | ||||
| msgstr "刷新" | ||||
|  | ||||
|  | ||||
| @ -1,8 +1,9 @@ | ||||
| import MDCaddyStandalone from "@goauthentik/docs/providers/proxy/_caddy_standalone.md"; | ||||
| import MDNginxIngress from "@goauthentik/docs/providers/proxy/_nginx_ingress.md"; | ||||
| import MDNginxPM from "@goauthentik/docs/providers/proxy/_nginx_proxy_manager.md"; | ||||
| import MDNginxStandalone from "@goauthentik/docs/providers/proxy/_nginx_standalone.md"; | ||||
| import MDTraefikCompose from "@goauthentik/docs/providers/proxy/_traefik_compose.md"; | ||||
| import MDTraefikIngres from "@goauthentik/docs/providers/proxy/_traefik_ingress.md"; | ||||
| import MDTraefikIngress from "@goauthentik/docs/providers/proxy/_traefik_ingress.md"; | ||||
| import MDTraefikStandalone from "@goauthentik/docs/providers/proxy/_traefik_standalone.md"; | ||||
| import { DEFAULT_CONFIG } from "@goauthentik/web/api/Config"; | ||||
| import { EVENT_REFRESH } from "@goauthentik/web/constants"; | ||||
| @ -16,6 +17,7 @@ import "@goauthentik/web/elements/buttons/SpinnerButton"; | ||||
| import "@goauthentik/web/elements/events/ObjectChangelog"; | ||||
| import "@goauthentik/web/pages/providers/RelatedApplicationButton"; | ||||
| import "@goauthentik/web/pages/providers/proxy/ProxyProviderForm"; | ||||
| import { convertToSlug } from "@goauthentik/web/utils"; | ||||
|  | ||||
| import { t } from "@lingui/macro"; | ||||
|  | ||||
| @ -120,6 +122,50 @@ export class ProxyProviderViewPage extends LitElement { | ||||
|         return markdown; | ||||
|     } | ||||
|  | ||||
|     renderConfig(): TemplateResult { | ||||
|         const serves = [ | ||||
|             { | ||||
|                 label: t`Nginx (Ingress)`, | ||||
|                 md: MDNginxIngress, | ||||
|             }, | ||||
|             { | ||||
|                 label: t`Nginx (Proxy Manager)`, | ||||
|                 md: MDNginxPM, | ||||
|             }, | ||||
|             { | ||||
|                 label: t`Nginx (standalone)`, | ||||
|                 md: MDNginxStandalone, | ||||
|             }, | ||||
|             { | ||||
|                 label: t`Traefik (Ingress)`, | ||||
|                 md: MDTraefikIngress, | ||||
|             }, | ||||
|             { | ||||
|                 label: t`Traefik (Compose)`, | ||||
|                 md: MDTraefikCompose, | ||||
|             }, | ||||
|             { | ||||
|                 label: t`Traefik (Standalone)`, | ||||
|                 md: MDTraefikStandalone, | ||||
|             }, | ||||
|             { | ||||
|                 label: t`Caddy (Standalone)`, | ||||
|                 md: MDCaddyStandalone, | ||||
|             }, | ||||
|         ]; | ||||
|         return html`<ak-tabs pageIdentifier="proxy-setup"> | ||||
|             ${serves.map((server) => { | ||||
|                 return html`<section | ||||
|                     slot="page-${convertToSlug(server.label)}" | ||||
|                     data-tab-title="${server.label}" | ||||
|                     class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" | ||||
|                 > | ||||
|                     <ak-markdown .md=${this.renderConfigTemplate(server.md)}></ak-markdown> | ||||
|                 </section>`; | ||||
|             })}</ak-tabs | ||||
|         >`; | ||||
|     } | ||||
|  | ||||
|     render(): TemplateResult { | ||||
|         if (!this.provider) { | ||||
|             return html``; | ||||
| @ -257,64 +303,7 @@ export class ProxyProviderViewPage extends LitElement { | ||||
|                     <div class="pf-c-card__title">${t`Setup`}</div> | ||||
|                     <div class="pf-c-card__body"> | ||||
|                         ${isForward(this.provider?.mode || ProxyMode.Proxy) | ||||
|                             ? html` | ||||
|                                   <ak-tabs pageIdentifier="proxy-setup"> | ||||
|                                       <section | ||||
|                                           slot="page-nginx-ingress" | ||||
|                                           data-tab-title="${t`Nginx (Ingress)`}" | ||||
|                                           class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" | ||||
|                                       > | ||||
|                                           <ak-markdown | ||||
|                                               .md=${this.renderConfigTemplate(MDNginxIngress)} | ||||
|                                           ></ak-markdown> | ||||
|                                       </section> | ||||
|                                       <section | ||||
|                                           slot="page-nginx-proxy-manager" | ||||
|                                           data-tab-title="${t`Nginx (Proxy Manager)`}" | ||||
|                                           class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" | ||||
|                                       > | ||||
|                                           <ak-markdown | ||||
|                                               .md=${this.renderConfigTemplate(MDNginxPM)} | ||||
|                                           ></ak-markdown> | ||||
|                                       </section> | ||||
|                                       <section | ||||
|                                           slot="page-nginx-standalone" | ||||
|                                           data-tab-title="${t`Nginx (standalone)`}" | ||||
|                                           class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" | ||||
|                                       > | ||||
|                                           <ak-markdown | ||||
|                                               .md=${this.renderConfigTemplate(MDNginxStandalone)} | ||||
|                                           ></ak-markdown> | ||||
|                                       </section> | ||||
|                                       <section | ||||
|                                           slot="page-traefik-ingress" | ||||
|                                           data-tab-title="${t`Traefik (Ingress)`}" | ||||
|                                           class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" | ||||
|                                       > | ||||
|                                           <ak-markdown | ||||
|                                               .md=${this.renderConfigTemplate(MDTraefikIngres)} | ||||
|                                           ></ak-markdown> | ||||
|                                       </section> | ||||
|                                       <section | ||||
|                                           slot="page-traefik-compose" | ||||
|                                           data-tab-title="${t`Traefik (Compose)`}" | ||||
|                                           class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" | ||||
|                                       > | ||||
|                                           <ak-markdown | ||||
|                                               .md=${this.renderConfigTemplate(MDTraefikCompose)} | ||||
|                                           ></ak-markdown> | ||||
|                                       </section> | ||||
|                                       <section | ||||
|                                           slot="page-traefik-standalone" | ||||
|                                           data-tab-title="${t`Traefik (Standalone)`}" | ||||
|                                           class="pf-c-page__main-section pf-m-light pf-m-no-padding-mobile" | ||||
|                                       > | ||||
|                                           <ak-markdown | ||||
|                                               .md=${this.renderConfigTemplate(MDTraefikStandalone)} | ||||
|                                           ></ak-markdown> | ||||
|                                       </section> | ||||
|                                   </ak-tabs> | ||||
|                               ` | ||||
|                             ? html` ${this.renderConfig()} ` | ||||
|                             : html` <p>${t`No additional setup is required.`}</p> `} | ||||
|                     </div> | ||||
|                 </div> | ||||
|  | ||||
							
								
								
									
										22
									
								
								website/docs/providers/proxy/_caddy_standalone.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								website/docs/providers/proxy/_caddy_standalone.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| Use the following configuration: | ||||
|  | ||||
| ``` | ||||
| app.company { | ||||
|     # always forward outpost path to actual outpost | ||||
|     reverse_proxy /outpost.goauthentik.io/* http://outpost.company:9000 | ||||
|  | ||||
|     # forward authentication to outpost | ||||
|     forward_auth http://outpost.company:9000 { | ||||
|         uri /outpost.goauthentik.io/auth/caddy | ||||
|  | ||||
|         # capitalization of the headers is important, otherwise they will be empty | ||||
|         copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version | ||||
|  | ||||
|         # optional, in this config trust all private ranges, should probably be set to the outposts IP | ||||
|         trusted_proxies private_ranges | ||||
|     } | ||||
|  | ||||
|     # actual site configuration below, for example | ||||
|     reverse_proxy localhost:1234 | ||||
| } | ||||
| ``` | ||||
| @ -130,3 +130,23 @@ import EnvoyIstio from "./_envoy_istio.md"; | ||||
|  | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
|  | ||||
| ## Caddy | ||||
|  | ||||
| :::info | ||||
| Requires authentik 2022.8 | ||||
| ::: | ||||
|  | ||||
| <Tabs | ||||
|   defaultValue="caddy-standalone" | ||||
|   values={[ | ||||
|     {label: 'Caddy (standalone)', value: 'caddy-standalone'}, | ||||
|   ]}> | ||||
|   <TabItem value="caddy-standalone"> | ||||
|  | ||||
| import CaddyStandalone from "./_caddy_standalone.md"; | ||||
|  | ||||
| <CaddyStandalone /> | ||||
|  | ||||
|   </TabItem> | ||||
| </Tabs> | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens L
					Jens L