mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-11 13:45:25 +03:00
add support for user passthru from upstream proxies
This commit is contained in:
parent
46d60e4a39
commit
dd730bf6c7
@ -22,6 +22,9 @@ location /auth {
|
|||||||
proxy_set_header Cookie $http_cookie;
|
proxy_set_header Cookie $http_cookie;
|
||||||
proxy_set_header X-CSRF-TOKEN "1";
|
proxy_set_header X-CSRF-TOKEN "1";
|
||||||
|
|
||||||
|
# include headers from common auth proxies
|
||||||
|
include proxy_trusted_headers.conf;
|
||||||
|
|
||||||
## Basic Proxy Configuration
|
## Basic Proxy Configuration
|
||||||
proxy_pass_request_body off;
|
proxy_pass_request_body off;
|
||||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
|
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
# these headers will be copied to the /auth request and are available
|
||||||
|
# to be mapped in the config to Frigate's remote-user header
|
||||||
|
|
||||||
|
# List of headers sent by common authentication proxies:
|
||||||
|
# - Authelia
|
||||||
|
# - Traefik forward auth
|
||||||
|
# - oauth2_proxy
|
||||||
|
# - Authentik
|
||||||
|
|
||||||
|
proxy_set_header Remote-User $http_remote_user;
|
||||||
|
proxy_set_header Remote-Groups $http_remote_groups;
|
||||||
|
proxy_set_header Remote-Email $http_remote_email;
|
||||||
|
proxy_set_header Remote-Name $http_remote_name;
|
||||||
|
proxy_set_header X-Forwarded-User $http_x_forwarded_user;
|
||||||
|
proxy_set_header X-Forwarded-Groups $http_x_forwarded_groups;
|
||||||
|
proxy_set_header X-Forwarded-Email $http_x_forwarded_email;
|
||||||
|
proxy_set_header X-Forwarded-Preferred-Username $http_x_forwarded_preferred_username;
|
||||||
|
proxy_set_header X-authentik-username $http_x_authentik_username;
|
||||||
|
proxy_set_header X-authentik-groups $http_x_authentik_groups;
|
||||||
|
proxy_set_header X-authentik-email $http_x_authentik_email;
|
||||||
|
proxy_set_header X-authentik-name $http_x_authentik_name;
|
||||||
|
proxy_set_header X-authentik-uid $http_x_authentik_uid;
|
||||||
@ -21,7 +21,7 @@ from frigate.api.export import ExportBp
|
|||||||
from frigate.api.media import MediaBp
|
from frigate.api.media import MediaBp
|
||||||
from frigate.api.preview import PreviewBp
|
from frigate.api.preview import PreviewBp
|
||||||
from frigate.api.review import ReviewBp
|
from frigate.api.review import ReviewBp
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import AuthModeEnum, FrigateConfig
|
||||||
from frigate.const import CONFIG_DIR
|
from frigate.const import CONFIG_DIR
|
||||||
from frigate.events.external import ExternalEventProcessor
|
from frigate.events.external import ExternalEventProcessor
|
||||||
from frigate.models import Event, Timeline
|
from frigate.models import Event, Timeline
|
||||||
@ -86,7 +86,9 @@ def create_app(
|
|||||||
app.plus_api = plus_api
|
app.plus_api = plus_api
|
||||||
app.camera_error_image = None
|
app.camera_error_image = None
|
||||||
app.stats_emitter = stats_emitter
|
app.stats_emitter = stats_emitter
|
||||||
app.jwt_token = get_jwt_secret() if frigate_config.auth.enabled else None
|
app.jwt_token = (
|
||||||
|
get_jwt_secret() if frigate_config.auth.mode == AuthModeEnum.native else None
|
||||||
|
)
|
||||||
# update the request_address with the x-forwarded-for header from nginx
|
# update the request_address with the x-forwarded-for header from nginx
|
||||||
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1)
|
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1)
|
||||||
# initialize the rate limiter for the login endpoint
|
# initialize the rate limiter for the login endpoint
|
||||||
|
|||||||
@ -17,6 +17,7 @@ from flask_limiter import Limiter
|
|||||||
from joserfc import jwt
|
from joserfc import jwt
|
||||||
from peewee import DoesNotExist
|
from peewee import DoesNotExist
|
||||||
|
|
||||||
|
from frigate.config import AuthModeEnum
|
||||||
from frigate.const import CONFIG_DIR, JWT_SECRET_ENV_VAR, PASSWORD_HASH_ALGORITHM
|
from frigate.const import CONFIG_DIR, JWT_SECRET_ENV_VAR, PASSWORD_HASH_ALGORITHM
|
||||||
from frigate.models import User
|
from frigate.models import User
|
||||||
|
|
||||||
@ -175,12 +176,24 @@ def auth():
|
|||||||
if request.headers.get("x-server-port", 0, type=int) == 5000:
|
if request.headers.get("x-server-port", 0, type=int) == 5000:
|
||||||
return success_response
|
return success_response
|
||||||
|
|
||||||
|
# if proxy auth mode
|
||||||
|
if current_app.frigate_config.auth.mode == AuthModeEnum.proxy:
|
||||||
|
# pass the user header value from the upstream proxy if a mapping is specified
|
||||||
|
# or use anonymous if none are specified
|
||||||
|
if current_app.frigate_config.auth.header_map.user is not None:
|
||||||
|
upstream_user_header_value = request.headers.get(
|
||||||
|
current_app.frigate_config.auth.header_map.user,
|
||||||
|
type=str,
|
||||||
|
default="anonymous",
|
||||||
|
)
|
||||||
|
success_response.headers["remote-user"] = upstream_user_header_value
|
||||||
|
else:
|
||||||
|
success_response.headers["remote-user"] = "anonymous"
|
||||||
|
return success_response
|
||||||
|
|
||||||
fail_response = make_response({}, 401)
|
fail_response = make_response({}, 401)
|
||||||
fail_response.headers["location"] = "/login"
|
fail_response.headers["location"] = "/login"
|
||||||
|
|
||||||
if not current_app.frigate_config.auth.enabled:
|
|
||||||
return success_response
|
|
||||||
|
|
||||||
JWT_COOKIE_NAME = current_app.frigate_config.auth.cookie_name
|
JWT_COOKIE_NAME = current_app.frigate_config.auth.cookie_name
|
||||||
JWT_REFRESH = current_app.frigate_config.auth.refresh_time
|
JWT_REFRESH = current_app.frigate_config.auth.refresh_time
|
||||||
JWT_SESSION_LENGTH = current_app.frigate_config.auth.session_length
|
JWT_SESSION_LENGTH = current_app.frigate_config.auth.session_length
|
||||||
|
|||||||
@ -27,7 +27,7 @@ from frigate.comms.dispatcher import Communicator, Dispatcher
|
|||||||
from frigate.comms.inter_process import InterProcessCommunicator
|
from frigate.comms.inter_process import InterProcessCommunicator
|
||||||
from frigate.comms.mqtt import MqttClient
|
from frigate.comms.mqtt import MqttClient
|
||||||
from frigate.comms.ws import WebSocketClient
|
from frigate.comms.ws import WebSocketClient
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import AuthModeEnum, FrigateConfig
|
||||||
from frigate.const import (
|
from frigate.const import (
|
||||||
CACHE_DIR,
|
CACHE_DIR,
|
||||||
CLIPS_DIR,
|
CLIPS_DIR,
|
||||||
@ -592,7 +592,7 @@ class FrigateApp:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def init_auth(self) -> None:
|
def init_auth(self) -> None:
|
||||||
if self.config.auth.enabled:
|
if self.config.auth.mode == AuthModeEnum.native:
|
||||||
if User.select().count() == 0:
|
if User.select().count() == 0:
|
||||||
password = secrets.token_hex(16)
|
password = secrets.token_hex(16)
|
||||||
password_hash = hash_password(
|
password_hash = hash_password(
|
||||||
|
|||||||
@ -116,8 +116,19 @@ class UIConfig(FrigateBaseModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AuthModeEnum(str, Enum):
|
||||||
|
native = "native"
|
||||||
|
proxy = "proxy"
|
||||||
|
|
||||||
|
|
||||||
|
class HeaderMappingConfig(FrigateBaseModel):
|
||||||
|
user: str = Field(
|
||||||
|
default=None, title="Header name from upstream proxy to identify user."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AuthConfig(FrigateBaseModel):
|
class AuthConfig(FrigateBaseModel):
|
||||||
enabled: bool = Field(default=False, title="Enable authentication")
|
mode: AuthModeEnum = Field(default=AuthModeEnum.native, title="Authentication mode")
|
||||||
reset_admin_password: bool = Field(
|
reset_admin_password: bool = Field(
|
||||||
default=False, title="Reset the admin password on startup"
|
default=False, title="Reset the admin password on startup"
|
||||||
)
|
)
|
||||||
@ -132,6 +143,10 @@ class AuthConfig(FrigateBaseModel):
|
|||||||
title="Refresh the session if it is going to expire in this many seconds",
|
title="Refresh the session if it is going to expire in this many seconds",
|
||||||
ge=30,
|
ge=30,
|
||||||
)
|
)
|
||||||
|
header_map: Optional[HeaderMappingConfig] = Field(
|
||||||
|
default_factory=HeaderMappingConfig,
|
||||||
|
title="Header mapping definitions for proxy auth mode.",
|
||||||
|
)
|
||||||
failed_login_rate_limit: Optional[str] = Field(
|
failed_login_rate_limit: Optional[str] = Field(
|
||||||
default="1/second;5/minute;20/hour",
|
default="1/second;5/minute;20/hour",
|
||||||
title="Rate limits for failed login attempts.",
|
title="Rate limits for failed login attempts.",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user