Compare commits
11 Commits
version/20
...
version/20
| Author | SHA1 | Date | |
|---|---|---|---|
| e81d3dad3e | |||
| 5aabaebd96 | |||
| 7b60bca297 | |||
| a07d7456c8 | |||
| f33369bf0c | |||
| 1abcff39c7 | |||
| c1caf84d92 | |||
| 86c069fe64 | |||
| ce0140ef67 | |||
| bba43c5109 | |||
| d99a415502 |
@ -1,5 +1,5 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 2021.2.4-stable
|
current_version = 2021.2.5-stable
|
||||||
tag = True
|
tag = True
|
||||||
commit = True
|
commit = True
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*)
|
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-(?P<release>.*)
|
||||||
|
|||||||
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
@ -18,11 +18,11 @@ jobs:
|
|||||||
- name: Building Docker Image
|
- name: Building Docker Image
|
||||||
run: docker build
|
run: docker build
|
||||||
--no-cache
|
--no-cache
|
||||||
-t beryju/authentik:2021.2.4-stable
|
-t beryju/authentik:2021.2.5-stable
|
||||||
-t beryju/authentik:latest
|
-t beryju/authentik:latest
|
||||||
-f Dockerfile .
|
-f Dockerfile .
|
||||||
- name: Push Docker Container to Registry (versioned)
|
- name: Push Docker Container to Registry (versioned)
|
||||||
run: docker push beryju/authentik:2021.2.4-stable
|
run: docker push beryju/authentik:2021.2.5-stable
|
||||||
- name: Push Docker Container to Registry (latest)
|
- name: Push Docker Container to Registry (latest)
|
||||||
run: docker push beryju/authentik:latest
|
run: docker push beryju/authentik:latest
|
||||||
build-proxy:
|
build-proxy:
|
||||||
@ -48,11 +48,11 @@ jobs:
|
|||||||
cd outpost/
|
cd outpost/
|
||||||
docker build \
|
docker build \
|
||||||
--no-cache \
|
--no-cache \
|
||||||
-t beryju/authentik-proxy:2021.2.4-stable \
|
-t beryju/authentik-proxy:2021.2.5-stable \
|
||||||
-t beryju/authentik-proxy:latest \
|
-t beryju/authentik-proxy:latest \
|
||||||
-f proxy.Dockerfile .
|
-f proxy.Dockerfile .
|
||||||
- name: Push Docker Container to Registry (versioned)
|
- name: Push Docker Container to Registry (versioned)
|
||||||
run: docker push beryju/authentik-proxy:2021.2.4-stable
|
run: docker push beryju/authentik-proxy:2021.2.5-stable
|
||||||
- name: Push Docker Container to Registry (latest)
|
- name: Push Docker Container to Registry (latest)
|
||||||
run: docker push beryju/authentik-proxy:latest
|
run: docker push beryju/authentik-proxy:latest
|
||||||
build-static:
|
build-static:
|
||||||
@ -69,11 +69,11 @@ jobs:
|
|||||||
cd web/
|
cd web/
|
||||||
docker build \
|
docker build \
|
||||||
--no-cache \
|
--no-cache \
|
||||||
-t beryju/authentik-static:2021.2.4-stable \
|
-t beryju/authentik-static:2021.2.5-stable \
|
||||||
-t beryju/authentik-static:latest \
|
-t beryju/authentik-static:latest \
|
||||||
-f Dockerfile .
|
-f Dockerfile .
|
||||||
- name: Push Docker Container to Registry (versioned)
|
- name: Push Docker Container to Registry (versioned)
|
||||||
run: docker push beryju/authentik-static:2021.2.4-stable
|
run: docker push beryju/authentik-static:2021.2.5-stable
|
||||||
- name: Push Docker Container to Registry (latest)
|
- name: Push Docker Container to Registry (latest)
|
||||||
run: docker push beryju/authentik-static:latest
|
run: docker push beryju/authentik-static:latest
|
||||||
test-release:
|
test-release:
|
||||||
@ -107,5 +107,5 @@ jobs:
|
|||||||
SENTRY_PROJECT: authentik
|
SENTRY_PROJECT: authentik
|
||||||
SENTRY_URL: https://sentry.beryju.org
|
SENTRY_URL: https://sentry.beryju.org
|
||||||
with:
|
with:
|
||||||
tagName: 2021.2.4-stable
|
tagName: 2021.2.5-stable
|
||||||
environment: beryjuorg-prod
|
environment: beryjuorg-prod
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
"""authentik"""
|
"""authentik"""
|
||||||
__version__ = "2021.2.4-stable"
|
__version__ = "2021.2.5-stable"
|
||||||
|
|||||||
@ -41,6 +41,9 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</ak-dropdown>
|
</ak-dropdown>
|
||||||
|
<button role="ak-refresh" class="pf-c-button pf-m-primary">
|
||||||
|
{% trans 'Refresh' %}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{% include 'partials/pagination.html' %}
|
{% include 'partials/pagination.html' %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,6 +9,7 @@ from django.http import HttpRequest, HttpResponse
|
|||||||
SESSION_IMPERSONATE_USER = "authentik_impersonate_user"
|
SESSION_IMPERSONATE_USER = "authentik_impersonate_user"
|
||||||
SESSION_IMPERSONATE_ORIGINAL_USER = "authentik_impersonate_original_user"
|
SESSION_IMPERSONATE_ORIGINAL_USER = "authentik_impersonate_original_user"
|
||||||
LOCAL = local()
|
LOCAL = local()
|
||||||
|
RESPONSE_HEADER_ID = "X-authentik-id"
|
||||||
|
|
||||||
|
|
||||||
class ImpersonateMiddleware:
|
class ImpersonateMiddleware:
|
||||||
@ -43,7 +44,7 @@ class RequestIDMiddleware:
|
|||||||
setattr(request, "request_id", request_id)
|
setattr(request, "request_id", request_id)
|
||||||
LOCAL.authentik = {"request_id": request_id}
|
LOCAL.authentik = {"request_id": request_id}
|
||||||
response = self.get_response(request)
|
response = self.get_response(request)
|
||||||
response["X-authentik-id"] = request.request_id
|
response[RESPONSE_HEADER_ID] = request.request_id
|
||||||
del LOCAL.authentik["request_id"]
|
del LOCAL.authentik["request_id"]
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
from guardian.shortcuts import get_anonymous_user
|
from guardian.shortcuts import get_anonymous_user
|
||||||
from structlog import get_logger
|
from structlog import get_logger
|
||||||
|
|
||||||
|
from authentik.core.models import User
|
||||||
from authentik.events.models import (
|
from authentik.events.models import (
|
||||||
Event,
|
Event,
|
||||||
Notification,
|
Notification,
|
||||||
@ -53,7 +54,8 @@ def event_trigger_handler(event_uuid: str, trigger_name: str):
|
|||||||
return
|
return
|
||||||
|
|
||||||
LOGGER.debug("e(trigger): checking if trigger applies", trigger=trigger)
|
LOGGER.debug("e(trigger): checking if trigger applies", trigger=trigger)
|
||||||
policy_engine = PolicyEngine(trigger, get_anonymous_user())
|
user = User.objects.filter(pk=event.user.get("pk")).first() or get_anonymous_user()
|
||||||
|
policy_engine = PolicyEngine(trigger, user)
|
||||||
policy_engine.mode = PolicyEngineMode.MODE_OR
|
policy_engine.mode = PolicyEngineMode.MODE_OR
|
||||||
policy_engine.empty_result = False
|
policy_engine.empty_result = False
|
||||||
policy_engine.use_cache = False
|
policy_engine.use_cache = False
|
||||||
|
|||||||
@ -18,6 +18,8 @@ from django.core.asgi import get_asgi_application
|
|||||||
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
|
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
|
from authentik.core.middleware import RESPONSE_HEADER_ID
|
||||||
|
|
||||||
# DJANGO_SETTINGS_MODULE is set in gunicorn.conf.py
|
# DJANGO_SETTINGS_MODULE is set in gunicorn.conf.py
|
||||||
|
|
||||||
defuse_stdlib()
|
defuse_stdlib()
|
||||||
@ -67,6 +69,7 @@ class ASGILogger:
|
|||||||
status_code: int
|
status_code: int
|
||||||
start: float
|
start: float
|
||||||
content_length: int
|
content_length: int
|
||||||
|
request_id: str
|
||||||
|
|
||||||
def __init__(self, app: ASGIApp):
|
def __init__(self, app: ASGIApp):
|
||||||
self.app = app
|
self.app = app
|
||||||
@ -75,23 +78,29 @@ class ASGILogger:
|
|||||||
self.scope = scope
|
self.scope = scope
|
||||||
self.content_length = 0
|
self.content_length = 0
|
||||||
self.headers = dict(scope.get("headers", []))
|
self.headers = dict(scope.get("headers", []))
|
||||||
|
self.request_id = ""
|
||||||
|
|
||||||
async def send_hooked(message: Message) -> None:
|
async def send_hooked(message: Message) -> None:
|
||||||
"""Hooked send method, which records status code and content-length, and for the final
|
"""Hooked send method, which records status code and content-length, and for the final
|
||||||
requests logs it"""
|
requests logs it"""
|
||||||
headers = dict(message.get("headers", []))
|
headers = dict(message.get("headers", []))
|
||||||
|
|
||||||
if "status" in message:
|
if "status" in message:
|
||||||
self.status_code = message["status"]
|
self.status_code = message["status"]
|
||||||
|
|
||||||
if b"Content-Length" in headers:
|
if b"Content-Length" in headers:
|
||||||
self.content_length += int(headers.get(b"Content-Length", b"0"))
|
self.content_length += int(headers.get(b"Content-Length", b"0"))
|
||||||
|
|
||||||
|
if message["type"] == "http.response.start":
|
||||||
|
response_headers = dict(message["headers"])
|
||||||
|
self.request_id = response_headers.get(
|
||||||
|
RESPONSE_HEADER_ID.encode(), b""
|
||||||
|
).decode()
|
||||||
|
|
||||||
if message["type"] == "http.response.body" and not message.get(
|
if message["type"] == "http.response.body" and not message.get(
|
||||||
"more_body", None
|
"more_body", True
|
||||||
):
|
):
|
||||||
runtime = int((time() - self.start) * 1000)
|
runtime = int((time() - self.start) * 1000)
|
||||||
self.log(runtime)
|
self.log(runtime, request_id=self.request_id)
|
||||||
await send(message)
|
await send(message)
|
||||||
|
|
||||||
self.start = time()
|
self.start = time()
|
||||||
@ -111,7 +120,7 @@ class ASGILogger:
|
|||||||
# Check if header has multiple values, and use the first one
|
# Check if header has multiple values, and use the first one
|
||||||
return client_ip.split(", ")[0]
|
return client_ip.split(", ")[0]
|
||||||
|
|
||||||
def log(self, runtime: float):
|
def log(self, runtime: float, **kwargs):
|
||||||
"""Outpot access logs in a structured format"""
|
"""Outpot access logs in a structured format"""
|
||||||
host = self._get_ip()
|
host = self._get_ip()
|
||||||
query_string = ""
|
query_string = ""
|
||||||
@ -125,6 +134,7 @@ class ASGILogger:
|
|||||||
status=self.status_code,
|
status=self.status_code,
|
||||||
size=self.content_length / 1000 if self.content_length > 0 else 0,
|
size=self.content_length / 1000 if self.content_length > 0 else 0,
|
||||||
runtime=runtime,
|
runtime=runtime,
|
||||||
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -9,13 +9,13 @@
|
|||||||
<div class="pf-c-card__body">
|
<div class="pf-c-card__body">
|
||||||
{% if connections.exists %}
|
{% if connections.exists %}
|
||||||
<p>{% trans 'Connected.' %}</p>
|
<p>{% trans 'Connected.' %}</p>
|
||||||
<a class="pf-c-button pf-m-danger"
|
<a class="pf-c-button pf-m-danger ak-root-link"
|
||||||
href="{% url 'authentik_sources_oauth:oauth-client-disconnect' source_slug=source.slug %}">
|
href="{% url 'authentik_sources_oauth:oauth-client-disconnect' source_slug=source.slug %}">
|
||||||
{% trans 'Disconnect' %}
|
{% trans 'Disconnect' %}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>Not connected.</p>
|
<p>Not connected.</p>
|
||||||
<a class="pf-c-button pf-m-primary"
|
<a class="pf-c-button pf-m-primary ak-root-link"
|
||||||
href="{% url 'authentik_sources_oauth:oauth-client-login' source_slug=source.slug %}">
|
href="{% url 'authentik_sources_oauth:oauth-client-login' source_slug=source.slug %}">
|
||||||
{% trans 'Connect' %}
|
{% trans 'Connect' %}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -19,7 +19,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
server:
|
server:
|
||||||
image: beryju/authentik:${AUTHENTIK_TAG:-2021.2.4-stable}
|
image: beryju/authentik:${AUTHENTIK_TAG:-2021.2.5-stable}
|
||||||
command: server
|
command: server
|
||||||
environment:
|
environment:
|
||||||
AUTHENTIK_REDIS__HOST: redis
|
AUTHENTIK_REDIS__HOST: redis
|
||||||
@ -45,7 +45,7 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
worker:
|
worker:
|
||||||
image: beryju/authentik:${AUTHENTIK_TAG:-2021.2.4-stable}
|
image: beryju/authentik:${AUTHENTIK_TAG:-2021.2.5-stable}
|
||||||
command: worker
|
command: worker
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
@ -62,7 +62,7 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
static:
|
static:
|
||||||
image: beryju/authentik-static:${AUTHENTIK_TAG:-2021.2.4-stable}
|
image: beryju/authentik-static:${AUTHENTIK_TAG:-2021.2.5-stable}
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
labels:
|
labels:
|
||||||
|
|||||||
@ -4,7 +4,7 @@ name: authentik
|
|||||||
home: https://goauthentik.io
|
home: https://goauthentik.io
|
||||||
sources:
|
sources:
|
||||||
- https://github.com/BeryJu/authentik
|
- https://github.com/BeryJu/authentik
|
||||||
version: "2021.2.4-stable"
|
version: "2021.2.5-stable"
|
||||||
icon: https://raw.githubusercontent.com/BeryJu/authentik/master/web/icons/icon.svg
|
icon: https://raw.githubusercontent.com/BeryJu/authentik/master/web/icons/icon.svg
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: postgresql
|
- name: postgresql
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|-----------------------------------|-------------------------|-------------|
|
|-----------------------------------|-------------------------|-------------|
|
||||||
| image.name | beryju/authentik | Image used to run the authentik server and worker |
|
| image.name | beryju/authentik | Image used to run the authentik server and worker |
|
||||||
| image.name_static | beryju/authentik-static | Image used to run the authentik static server (CSS and JS Files) |
|
| image.name_static | beryju/authentik-static | Image used to run the authentik static server (CSS and JS Files) |
|
||||||
| image.tag | 2021.2.4-stable | Image tag |
|
| image.tag | 2021.2.5-stable | Image tag |
|
||||||
| image.pullPolicy | IfNotPresent | Image Pull Policy used for all deployments |
|
| image.pullPolicy | IfNotPresent | Image Pull Policy used for all deployments |
|
||||||
| serverReplicas | 1 | Replicas for the Server deployment |
|
| serverReplicas | 1 | Replicas for the Server deployment |
|
||||||
| workerReplicas | 1 | Replicas for the Worker deployment |
|
| workerReplicas | 1 | Replicas for the Worker deployment |
|
||||||
|
|||||||
@ -99,10 +99,12 @@ spec:
|
|||||||
httpGet:
|
httpGet:
|
||||||
path: /-/health/live/
|
path: /-/health/live/
|
||||||
port: http
|
port: http
|
||||||
|
initialDelaySeconds: 15
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /-/health/ready/
|
path: /-/health/ready/
|
||||||
port: http
|
port: http
|
||||||
|
initialDelaySeconds: 15
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: 100m
|
cpu: 100m
|
||||||
|
|||||||
@ -5,7 +5,7 @@ image:
|
|||||||
name: beryju/authentik
|
name: beryju/authentik
|
||||||
name_static: beryju/authentik-static
|
name_static: beryju/authentik-static
|
||||||
name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended
|
name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended
|
||||||
tag: 2021.2.4-stable
|
tag: 2021.2.5-stable
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
serverReplicas: 1
|
serverReplicas: 1
|
||||||
|
|||||||
@ -49,12 +49,14 @@ func NewAPIController(pbURL url.URL, token string) *APIController {
|
|||||||
// create the API client, with the transport
|
// create the API client, with the transport
|
||||||
apiClient := client.New(transport, strfmt.Default)
|
apiClient := client.New(transport, strfmt.Default)
|
||||||
|
|
||||||
|
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, err := apiClient.Outposts.OutpostsOutpostsList(outposts.NewOutpostsOutpostsListParams(), auth)
|
outposts, err := apiClient.Outposts.OutpostsOutpostsList(outposts.NewOutpostsOutpostsListParams(), auth)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
log.WithError(err).Panic("Failed to fetch configuration")
|
||||||
}
|
}
|
||||||
outpost := outposts.Payload.Results[0]
|
outpost := outposts.Payload.Results[0]
|
||||||
doGlobalSetup(outpost.Config.(map[string]interface{}))
|
doGlobalSetup(outpost.Config.(map[string]interface{}))
|
||||||
@ -64,7 +66,7 @@ func NewAPIController(pbURL url.URL, token string) *APIController {
|
|||||||
Auth: auth,
|
Auth: auth,
|
||||||
token: token,
|
token: token,
|
||||||
|
|
||||||
logger: log.WithField("component", "ak-api-controller"),
|
logger: log,
|
||||||
|
|
||||||
reloadOffset: time.Duration(rand.Intn(10)) * time.Second,
|
reloadOffset: time.Duration(rand.Intn(10)) * time.Second,
|
||||||
|
|
||||||
|
|||||||
@ -40,7 +40,7 @@ func (ac *APIController) initWS(pbURL url.URL, outpostUUID strfmt.UUID) {
|
|||||||
}
|
}
|
||||||
ws.Dial(fmt.Sprintf(pathTemplate, scheme, pbURL.Host, outpostUUID.String()), header)
|
ws.Dial(fmt.Sprintf(pathTemplate, scheme, pbURL.Host, outpostUUID.String()), header)
|
||||||
|
|
||||||
ac.logger.WithField("component", "ak-ws").WithField("outpost", outpostUUID.String()).Debug("connecting to authentik")
|
ac.logger.WithField("logger", "authentik.outpost.ak-ws").WithField("outpost", outpostUUID.String()).Debug("connecting to authentik")
|
||||||
|
|
||||||
ac.wsConn = ws
|
ac.wsConn = ws
|
||||||
// Send hello message with our version
|
// Send hello message with our version
|
||||||
@ -52,7 +52,7 @@ func (ac *APIController) initWS(pbURL url.URL, outpostUUID strfmt.UUID) {
|
|||||||
}
|
}
|
||||||
err := ws.WriteJSON(msg)
|
err := ws.WriteJSON(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ac.logger.WithField("component", "ak-ws").WithError(err).Warning("Failed to hello to authentik")
|
ac.logger.WithField("logger", "authentik.outpost.ak-ws").WithError(err).Warning("Failed to hello to authentik")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func doGlobalSetup(config map[string]interface{}) {
|
func doGlobalSetup(config map[string]interface{}) {
|
||||||
log.SetFormatter(&log.JSONFormatter{})
|
log.SetFormatter(&log.JSONFormatter{
|
||||||
|
FieldMap: log.FieldMap{
|
||||||
|
log.FieldKeyMsg: "event",
|
||||||
|
log.FieldKeyTime: "timestamp",
|
||||||
|
},
|
||||||
|
})
|
||||||
switch config[ConfigLogLevel].(string) {
|
switch config[ConfigLogLevel].(string) {
|
||||||
case "debug":
|
case "debug":
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
|
|||||||
@ -31,7 +31,7 @@ func (s *Server) bundleProviders(providers []*models.ProxyOutpostConfig) []*prov
|
|||||||
bundles[idx] = &providerBundle{
|
bundles[idx] = &providerBundle{
|
||||||
s: s,
|
s: s,
|
||||||
Host: externalHost.Host,
|
Host: externalHost.Host,
|
||||||
log: log.WithField("component", "proxy-bundle").WithField("provider", provider.Name),
|
log: log.WithField("logger", "authentik.outpost.proxy-bundle").WithField("provider", provider.Name),
|
||||||
}
|
}
|
||||||
bundles[idx].Build(provider)
|
bundles[idx].Build(provider)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -129,7 +129,7 @@ func (pb *providerBundle) Build(provider *models.ProxyOutpostConfig) {
|
|||||||
log.Printf("%s", err)
|
log.Printf("%s", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
oauthproxy, err := NewOAuthProxy(opts)
|
oauthproxy, err := NewOAuthProxy(opts, provider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("ERROR: Failed to initialise OAuth2 Proxy: %v", err)
|
log.Errorf("ERROR: Failed to initialise OAuth2 Proxy: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@ -95,7 +95,7 @@ type loggingHandler struct {
|
|||||||
func LoggingHandler(h http.Handler) http.Handler {
|
func LoggingHandler(h http.Handler) http.Handler {
|
||||||
return loggingHandler{
|
return loggingHandler{
|
||||||
handler: h,
|
handler: h,
|
||||||
logger: log.WithField("component", "proxy-http-server"),
|
logger: log.WithField("logger", "authentik.outpost.proxy-http-server"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,19 +104,17 @@ func (h loggingHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
url := *req.URL
|
url := *req.URL
|
||||||
responseLogger := &responseLogger{w: w}
|
responseLogger := &responseLogger{w: w}
|
||||||
h.handler.ServeHTTP(responseLogger, req)
|
h.handler.ServeHTTP(responseLogger, req)
|
||||||
duration := float64(time.Since(t)) / float64(time.Second)
|
duration := float64(time.Since(t)) / float64(time.Millisecond)
|
||||||
h.logger.WithFields(log.Fields{
|
h.logger.WithFields(log.Fields{
|
||||||
"Client": req.RemoteAddr,
|
"host": req.RemoteAddr,
|
||||||
"Host": req.Host,
|
"vhost": req.Host,
|
||||||
"Protocol": req.Proto,
|
"request_protocol": req.Proto,
|
||||||
"RequestDuration": fmt.Sprintf("%0.3f", duration),
|
"runtime": fmt.Sprintf("%0.3f", duration),
|
||||||
"RequestMethod": req.Method,
|
"method": req.Method,
|
||||||
"ResponseSize": responseLogger.Size(),
|
"size": responseLogger.Size(),
|
||||||
"StatusCode": responseLogger.Status(),
|
"status": responseLogger.Status(),
|
||||||
"Timestamp": t,
|
"upstream": responseLogger.upstream,
|
||||||
"Upstream": responseLogger.upstream,
|
"request_useragent": req.UserAgent(),
|
||||||
"UserAgent": req.UserAgent(),
|
"request_username": responseLogger.authInfo,
|
||||||
"Username": responseLogger.authInfo,
|
|
||||||
}).Info(url.RequestURI())
|
}).Info(url.RequestURI())
|
||||||
// logger.PrintReq(responseLogger.authInfo, responseLogger.upstream, req, url, t, , )
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/oauth2-proxy/oauth2-proxy/pkg/sessions"
|
"github.com/oauth2-proxy/oauth2-proxy/pkg/sessions"
|
||||||
"github.com/oauth2-proxy/oauth2-proxy/pkg/upstream"
|
"github.com/oauth2-proxy/oauth2-proxy/pkg/upstream"
|
||||||
"github.com/oauth2-proxy/oauth2-proxy/providers"
|
"github.com/oauth2-proxy/oauth2-proxy/providers"
|
||||||
|
"goauthentik.io/outpost/pkg/models"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -92,8 +93,8 @@ type OAuthProxy struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewOAuthProxy creates a new instance of OAuthProxy from the options provided
|
// NewOAuthProxy creates a new instance of OAuthProxy from the options provided
|
||||||
func NewOAuthProxy(opts *options.Options) (*OAuthProxy, error) {
|
func NewOAuthProxy(opts *options.Options, provider *models.ProxyOutpostConfig) (*OAuthProxy, error) {
|
||||||
logger := log.WithField("component", "proxy").WithField("client-id", opts.ClientID)
|
logger := log.WithField("logger", "authentik.outpost.proxy").WithField("provider", provider.Name)
|
||||||
sessionStore, err := sessions.NewSessionStore(&opts.Session, &opts.Cookie)
|
sessionStore, err := sessions.NewSessionStore(&opts.Session, &opts.Cookie)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error initialising session store: %v", err)
|
return nil, fmt.Errorf("error initialising session store: %v", err)
|
||||||
@ -434,6 +435,7 @@ func (p *OAuthProxy) addHeadersForProxying(rw http.ResponseWriter, req *http.Req
|
|||||||
authVal := b64.StdEncoding.EncodeToString([]byte(username + ":" + password))
|
authVal := b64.StdEncoding.EncodeToString([]byte(username + ":" + password))
|
||||||
req.Header["Authorization"] = []string{fmt.Sprintf("Basic %s", authVal)}
|
req.Header["Authorization"] = []string{fmt.Sprintf("Basic %s", authVal)}
|
||||||
}
|
}
|
||||||
|
rw.Header().Set("GAP-Auth", session.PreferredUsername)
|
||||||
// Check if user has additional headers set that we should sent
|
// Check if user has additional headers set that we should sent
|
||||||
if additionalHeaders, ok := userAttributes["additionalHeaders"].(map[string]string); ok {
|
if additionalHeaders, ok := userAttributes["additionalHeaders"].(map[string]string); ok {
|
||||||
if additionalHeaders == nil {
|
if additionalHeaders == nil {
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -30,7 +31,7 @@ func NewServer(ac *ak.APIController) *Server {
|
|||||||
}
|
}
|
||||||
return &Server{
|
return &Server{
|
||||||
Handlers: make(map[string]*providerBundle),
|
Handlers: make(map[string]*providerBundle),
|
||||||
logger: log.WithField("component", "proxy-http-server"),
|
logger: log.WithField("logger", "authentik.outpost.proxy-http-server"),
|
||||||
defaultCert: defaultCert,
|
defaultCert: defaultCert,
|
||||||
ak: ac,
|
ak: ac,
|
||||||
}
|
}
|
||||||
@ -50,12 +51,15 @@ func (s *Server) handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.logger.WithField("host", r.Host).Debug("Host header does not match any we know of")
|
// Get a list of all host keys we know
|
||||||
s.logger.Printf("%v+\n", s.Handlers)
|
hostKeys := make([]string, 0, len(s.Handlers))
|
||||||
w.WriteHeader(400)
|
for k := range s.Handlers {
|
||||||
|
hostKeys = append(hostKeys, k)
|
||||||
|
}
|
||||||
|
s.logger.WithField("host", r.Host).WithField("known-hosts", strings.Join(hostKeys, ", ")).Debug("Host header does not match any we know of")
|
||||||
|
w.WriteHeader(404)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.logger.WithField("host", r.Host).Debug("passing request from host head")
|
|
||||||
handler.ServeHTTP(w, r)
|
handler.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
const VERSION = "2021.2.4-stable"
|
const VERSION = "2021.2.5-stable"
|
||||||
|
|||||||
@ -28,4 +28,4 @@ export const ColorStyles = css`
|
|||||||
background-color: var(--pf-global--danger-color--100);
|
background-color: var(--pf-global--danger-color--100);
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const VERSION = "2021.2.4-stable";
|
export const VERSION = "2021.2.5-stable";
|
||||||
|
|||||||
@ -55,7 +55,12 @@ export class LibraryPage extends LitElement {
|
|||||||
apps?: AKResponse<Application>;
|
apps?: AKResponse<Application>;
|
||||||
|
|
||||||
static get styles(): CSSResult[] {
|
static get styles(): CSSResult[] {
|
||||||
return COMMON_STYLES;
|
return COMMON_STYLES.concat(css`
|
||||||
|
:host,
|
||||||
|
main {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
firstUpdated(): void {
|
firstUpdated(): void {
|
||||||
|
|||||||
@ -89,10 +89,14 @@ export class SiteShell extends LitElement {
|
|||||||
if (a.href === "") {
|
if (a.href === "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (a.href.startsWith("#")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const url = new URL(a.href);
|
const url = new URL(a.href);
|
||||||
const qs = url.search || "";
|
const qs = url.search || "";
|
||||||
a.href = `#${url.pathname}${qs}`;
|
const hash = (url.hash || "#").substring(2, Infinity);
|
||||||
|
a.href = `#${url.pathname}${qs}${hash}`;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.debug(`authentik/site-shell: error ${e}`);
|
console.debug(`authentik/site-shell: error ${e}`);
|
||||||
a.href = `#${a.href}`;
|
a.href = `#${a.href}`;
|
||||||
|
|||||||
@ -52,13 +52,13 @@ export class OutpostListPage extends TablePage<Outpost> {
|
|||||||
})}</ul>`,
|
})}</ul>`,
|
||||||
html`<ak-outpost-health outpostId=${item.pk}></ak-outpost-health>`,
|
html`<ak-outpost-health outpostId=${item.pk}></ak-outpost-health>`,
|
||||||
html`
|
html`
|
||||||
<ak-modal-button href="${Outpost.adminUrl(`${item.pk}/update`)}">
|
<ak-modal-button href="${Outpost.adminUrl(`${item.pk}/update/`)}">
|
||||||
<ak-spinner-button slot="trigger" class="pf-m-secondary">
|
<ak-spinner-button slot="trigger" class="pf-m-secondary">
|
||||||
${gettext("Edit")}
|
${gettext("Edit")}
|
||||||
</ak-spinner-button>
|
</ak-spinner-button>
|
||||||
<div slot="modal"></div>
|
<div slot="modal"></div>
|
||||||
</ak-modal-button>
|
</ak-modal-button>
|
||||||
<ak-modal-button href="${Outpost.adminUrl(`${item.pk}/delete`)}">
|
<ak-modal-button href="${Outpost.adminUrl(`${item.pk}/delete/`)}">
|
||||||
<ak-spinner-button slot="trigger" class="pf-m-danger">
|
<ak-spinner-button slot="trigger" class="pf-m-danger">
|
||||||
${gettext("Delete")}
|
${gettext("Delete")}
|
||||||
</ak-spinner-button>
|
</ak-spinner-button>
|
||||||
|
|||||||
@ -15,7 +15,7 @@ Download the latest `docker-compose.yml` from [here](https://raw.githubuserconte
|
|||||||
|
|
||||||
To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env`
|
To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env`
|
||||||
|
|
||||||
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.2.4-stable >> .env`
|
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.2.5-stable >> .env`
|
||||||
|
|
||||||
If this is a fresh authentik install run the following commands to generate a password:
|
If this is a fresh authentik install run the following commands to generate a password:
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ image:
|
|||||||
name: beryju/authentik
|
name: beryju/authentik
|
||||||
name_static: beryju/authentik-static
|
name_static: beryju/authentik-static
|
||||||
name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended
|
name_outposts: beryju/authentik # Prefix used for Outpost deployments, Outpost type and version is appended
|
||||||
tag: 2021.2.4-stable
|
tag: 2021.2.5-stable
|
||||||
|
|
||||||
serverReplicas: 1
|
serverReplicas: 1
|
||||||
workerReplicas: 1
|
workerReplicas: 1
|
||||||
|
|||||||
14
website/docs/releases/next.md
Normal file
14
website/docs/releases/next.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
title: Next release
|
||||||
|
---
|
||||||
|
|
||||||
|
## Headline Changes
|
||||||
|
|
||||||
|
- Simplify role-based access
|
||||||
|
|
||||||
|
Instead of having to create a Group Membership policy for every group you want to use, you can now select a Group and even a User directly in a binding.
|
||||||
|
|
||||||
|
When a group is selected, the binding behaves the same as if a Group Membership policy exists.
|
||||||
|
|
||||||
|
When a user is selected, the binding checks the user of the request, and denies the request when the user doesn't match.
|
||||||
|
|
||||||
Reference in New Issue
Block a user