goauthentik / authentik

The authentication glue you need.
https://goauthentik.io
Other
13.75k stars 926 forks source link

Authentik requires public schema #12154

Open drewburr opened 1 week ago

drewburr commented 1 week ago

Describe the bug Reopen of #9212

Authentik is documented to not require the public schema, but offers no documentation on how to customize. I've created schema authentik for user authentik, which is highest priority in the default search path. I see that Authentik honors this to a point during startup, but ultimately fails while attempting to create a table in public.

To Reproduce Steps to reproduce the behavior:

  1. Start with fresh PostgreSQL instance and Authentik install
  2. Create role and schema, revoke public access
    create role authentik;
    create schema authentik AUTHORIZATION authentik;
    REVOKE CREATE ON SCHEMA public FROM PUBLIC;
  3. Start Authentik using the authentik user for Postgres connections

Expected behavior Following the above example, Authentik is expected to use the authentik schema for all objects as it is first in the search path.

Screenshots If applicable, add screenshots to help explain your problem.

Logs Output of docker-compose logs or kubectl logs respectively

{"event": "Not running as root, disabling permission fixes", "level": "info", "logger": "bootstrap"}
{"event": "Loaded config", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254145.4650402, "file": "/authentik/lib/default.yml"}
{"event": "Loaded environment variables", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254145.4656966, "count": 73}
{"event": "Starting authentik bootstrap", "level": "info", "logger": "authentik.lib.config", "timestamp": 1732254145.8850715}
{"event": "PostgreSQL connection successful", "level": "info", "logger": "authentik.lib.config", "timestamp": 1732254145.89906}
{"event": "Redis Connection successful", "level": "info", "logger": "authentik.lib.config", "timestamp": 1732254145.9006288}
{"event": "Finished authentik bootstrap", "level": "info", "logger": "authentik.lib.config", "timestamp": 1732254145.9007132}
2024-11-22 05:42:25 [info     ] waiting to acquire database lock
2024-11-22 05:42:25 [info     ] Migration needs to be applied  migration=install_id.py
2024-11-22 05:42:26 [info     ] Migration finished applying    migration=install_id.py
2024-11-22 05:42:26 [info     ] Migration needs to be applied  migration=template_schema.py
2024-11-22 05:42:26 [info     ] Migration finished applying    migration=template_schema.py
2024-11-22 05:42:26 [info     ] Migration needs to be applied  migration=tenant_files.py
2024-11-22 05:42:26 [info     ] Migration finished applying    migration=tenant_files.py
2024-11-22 05:42:26 [info     ] Migration needs to be applied  migration=version_history_create.py
2024-11-22 05:42:26 [info     ] Migration finished applying    migration=version_history_create.py
2024-11-22 05:42:26 [info     ] Migration needs to be applied  migration=version_history_update.py
2024-11-22 05:42:26 [info     ] Migration finished applying    migration=version_history_update.py
2024-11-22 05:42:26 [info     ] applying django migrations
{"event": "Booting authentik", "level": "info", "logger": "authentik.lib.config", "timestamp": 1732254147.3684525, "version": "2024.10.2"}
{"event": "Enabled authentik enterprise", "level": "info", "logger": "authentik.lib.config", "timestamp": 1732254147.3701298}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3707888, "path": "authentik.enterprise.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3722105, "path": "authentik.enterprise.providers.microsoft_entra.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3732736, "path": "authentik.sources.ldap.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3740034, "path": "authentik.outposts.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3745244, "path": "authentik.enterprise.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.374882, "path": "authentik.providers.scim.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3753424, "path": "authentik.sources.kerberos.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3757663, "path": "authentik.stages.authenticator_webauthn.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3763847, "path": "authentik.events.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3787694, "path": "authentik.enterprise.providers.google_workspace.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3791833, "path": "authentik.sources.oauth.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3803213, "path": "authentik.sources.plex.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3807366, "path": "authentik.stages.authenticator_totp.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.381401, "path": "authentik.crypto.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.3817103, "path": "authentik.blueprints.settings"}
{"event": "Loaded app settings", "level": "debug", "logger": "authentik.lib.config", "timestamp": 1732254147.382218, "path": "authentik.admin.settings"}
{"domain_url": null, "event": "Loaded MMDB database", "file": "/geoip/GeoLite2-ASN.mmdb", "last_write": 1731602268.0, "level": "info", "logger": "authentik.events.context_processors.mmdb", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:27.851389"}
{"domain_url": null, "event": "Loaded MMDB database", "file": "/geoip/GeoLite2-City.mmdb", "last_write": 1731602268.0, "level": "info", "logger": "authentik.events.context_processors.mmdb", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:27.852184"}
{"app_name": "authentik.tenants", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.tenants.checks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.270115"}
{"app_name": "authentik.tenants", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.tenants.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.270512"}
{"app_name": "authentik.admin", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.admin.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.284287"}
{"app_name": "authentik.admin", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.admin.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.284619"}
{"app_name": "authentik.crypto", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.crypto.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.285448"}
{"app_name": "authentik.flows", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.flows.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.309980"}
{"app_name": "authentik.outposts", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.outposts.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.336636"}
{"app_name": "authentik.outposts", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.outposts.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.337416"}
{"app_name": "authentik.policies.reputation", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.policies.reputation.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.338015"}
{"app_name": "authentik.policies", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.policies.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.347163"}
{"app_name": "authentik.providers.oauth2", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.providers.oauth2.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.347558"}
{"app_name": "authentik.providers.proxy", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.providers.proxy.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.348032"}
{"app_name": "authentik.providers.proxy", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.providers.proxy.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.348383"}
{"app_name": "authentik.providers.scim", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.providers.scim.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.350327"}
{"app_name": "authentik.providers.scim", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.providers.scim.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.351191"}
{"app_name": "authentik.rbac", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.rbac.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.351997"}
{"app_name": "authentik.sources.kerberos", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.sources.kerberos.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.353572"}
{"app_name": "authentik.sources.kerberos", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.sources.kerberos.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.354063"}
{"app_name": "authentik.sources.ldap", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.sources.ldap.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.359152"}
{"app_name": "authentik.sources.ldap", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.sources.ldap.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.361898"}
{"app_name": "authentik.sources.oauth", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.sources.oauth.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.373383"}
{"app_name": "authentik.sources.saml", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.sources.saml.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.373798"}
{"app_name": "authentik.sources.scim", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.sources.scim.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.374324"}
{"app_name": "authentik.stages.authenticator_duo", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.stages.authenticator_duo.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.374824"}
{"app_name": "authentik.stages.authenticator_static", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.stages.authenticator_static.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.375205"}
{"app_name": "authentik.stages.authenticator_webauthn", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.stages.authenticator_webauthn.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.412212"}
{"app_name": "authentik.stages.email", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.stages.email.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.412441"}
{"app_name": "authentik.core", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.core.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.414174"}
{"app_name": "authentik.core", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.core.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.414265"}
{"app_name": "authentik.enterprise", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.enterprise.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.414662"}
{"app_name": "authentik.enterprise", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.enterprise.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.415067"}
{"app_name": "authentik.enterprise.providers.google_workspace", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.enterprise.providers.google_workspace.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.415681"}
{"app_name": "authentik.enterprise.providers.google_workspace", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.enterprise.providers.google_workspace.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.415985"}
{"app_name": "authentik.enterprise.providers.microsoft_entra", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.enterprise.providers.microsoft_entra.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.416446"}
{"app_name": "authentik.enterprise.providers.microsoft_entra", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.enterprise.providers.microsoft_entra.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.416749"}
{"app_name": "authentik.enterprise.providers.rac", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.enterprise.providers.rac.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.420894"}
{"app_name": "authentik.events", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.events.tasks", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.421234"}
{"app_name": "authentik.events", "domain_url": null, "event": "Imported related module", "level": "info", "logger": "authentik.blueprints.apps", "module": "authentik.events.signals", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:29.421318"}
{"domain_url": null, "event": "releasing database lock", "level": "info", "logger": "lifecycle.migrate", "pid": 7, "schema_name": "public", "timestamp": "2024-11-22T05:42:30.346869"}
Traceback (most recent call last):
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 103, in _execute
    return self.cursor.execute(sql)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django_prometheus/db/common.py", line 69, in execute
    return super().execute(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/psycopg/cursor.py", line 97, in execute
    raise ex.with_traceback(None)
psycopg.errors.InsufficientPrivilege: permission denied for schema public
LINE 1: CREATE TABLE "django_migrations" ("id" integer NOT NULL PRIM...
                     ^

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/migrations/recorder.py", line 78, in ensure_schema
    editor.create_model(self.Migration)
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/backends/base/schema.py", line 505, in create_model
    self.execute(sql, params or None)
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/backends/postgresql/schema.py", line 45, in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/backends/base/schema.py", line 202, in execute
    cursor.execute(sql, params)
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 79, in execute
    return self._execute_with_wrappers(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 100, in _execute
    with self.db.wrap_database_errors:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/backends/utils.py", line 103, in _execute
    return self.cursor.execute(sql)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django_prometheus/db/common.py", line 69, in execute
    return super().execute(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/psycopg/cursor.py", line 97, in execute
    raise ex.with_traceback(None)
django.db.utils.ProgrammingError: permission denied for schema public
LINE 1: CREATE TABLE "django_migrations" ("id" integer NOT NULL PRIM...

Version and Deployment (please complete the following information):

Additional context

Mirroring from #9212:

It should be made possible to override public to a different schema name, if not for security concerns alone (see CVE-2018-1058) then for compliance reasons.

Postgres 15 and above does not provide access to the public schema by default in order to address this concern and CVE-2018-1058. In security-conscious environments and those that are required to adhere to NIST benchmarks, Authentik would be expected to use a schema other than public (see CIS PostgreSQL 16 Benchmark 1.0.0 Checklist, latest available Nov. 2024).

To quote directly from the linked CIS Benchmark Checklist:

Rationale: Excessive DML grants can lead to unprivileged users changing or deleting information without proper authorization. ... For versions of PostgreSQL prior to version 15, CVE-2018-1058 is applicable and it is recommended that all privileges be revoked from the public schema for all users on all databases. If you have upgraded from one of these earlier releases, this CVE is not fixed for you during an upgrade. You can correct this CVE by issuing:

postgres=# REVOKE CREATE ON SCHEMA public FROM PUBLIC; REVOKE

This creates compliance hurdles for any entity that handles U.S Government contracts, due to Authentik's inability to fully satisfy the CIS Benchmark.

Please consider adding a configuration point such as AUTHENTIK_POSTGRESQL__SCHEMA to enable the use of alternate schemas, or honor the default search path for object creation and reference.