authentik icon indicating copy to clipboard operation
authentik copied to clipboard

Email sending is not using docker secrets

Open Akumatic opened this issue 1 year ago • 1 comments

Describe the bug The Python script behind ak test_email throws socket.gaierror when sending a test mail if docker secrets are used for the mail configuration. The test mail is sent and delivered successfully if the corresponding login information is saved directly in the environment variables.

I assume that this happens because the script takes the content of the environment variable literally and does not use the content behind it (e.g. /run/secrets/pass instead of the password itself, which is stored in the secret).

To Reproduce Steps to reproduce the behavior:

  1. Setup a working instance with docker compose
  2. Add environment variables for mail using docker secrets
worker:
    image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.8.0}
    container_name: authentik_worker
    restart: unless-stopped
    command: worker
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: /run/secrets/db_pass
      AUTHENTIK_SECRET_KEY: /run/secrets/secret_key
      AUTHENTIK_EMAIL__HOST: /run/secrets/mail_server
      AUTHENTIK_EMAIL__PORT: 587
      AUTHENTIK_EMAIL__USERNAME: /run/secrets/mail_user
      AUTHENTIK_EMAIL__PASSWORD: /run/secrets/mail_pass
      AUTHENTIK_EMAIL__USE_TLS: true
      AUTHENTIK_EMAIL__USE_SSL: false
      AUTHENTIK_EMAIL__TIMEOUT: 10
      AUTHENTIK_EMAIL__FROM: /run/secrets/mail_user
    user: root
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /srv/authentik/media:/media
      - /srv/authentik/certs:/certs
      - /srv/authentik/custom-templates:/templates
    depends_on:
      - postgresql
      - redis
    secrets:
      - db_pass
      - secret_key
      - mail_user
      - mail_pass
      - mail_server
  1. (Re)create worker container
  2. Execute ak test_email [my address] in worker container

Expected behavior An Email is delivered to [my address]

Logs Traceback of ak test_email

Switching to schema 'public'
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/manage.py", line 52, in <module>
    execute_from_command_line(sys.argv)
  File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/base.py", line 413, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/base.py", line 459, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/tenants/management/__init__.py", line 38, in handle
    self.handle_per_tenant(*args, **options)
  File "/ak-root/venv/lib/python3.12/site-packages/django/core/management/base.py", line 107, in wrapper
    res = handle_func(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/stages/email/management/commands/test_email.py", line 38, in handle_per_tenant
    send_mail(message.__dict__, stage.pk)
  File "/ak-root/venv/lib/python3.12/site-packages/celery/local.py", line 182, in __call__
    return self._get_current_object()(*a, **kw)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/celery/app/task.py", line 411, in __call__
    return self.run(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/celery/app/autoretry.py", line 60, in run
    ret = task.retry(exc=exc, **retry_kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/celery/app/task.py", line 720, in retry
    raise_with_context(exc or Retry('Task can be retried', None))
  File "/ak-root/venv/lib/python3.12/site-packages/celery/app/autoretry.py", line 38, in run
    return task._orig_run(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/stages/email/tasks.py", line 105, in send_mail
    raise exc
  File "/authentik/stages/email/tasks.py", line 73, in send_mail
    backend.open()
  File "/ak-root/venv/lib/python3.12/site-packages/django/core/mail/backends/smtp.py", line 86, in open
    self.connection = self.connection_class(
                      ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/smtplib.py", line 255, in __init__
    (code, msg) = self.connect(host, port)
                  ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/smtplib.py", line 341, in connect
    self.sock = self._get_socket(host, port, self.timeout)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/smtplib.py", line 312, in _get_socket
    return socket.create_connection((host, port), timeout,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/socket.py", line 841, in create_connection
    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/socket.py", line 976, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
socket.gaierror: [Errno -2] Name or service not known

Version and Deployment (please complete the following information):

  • authentik version: 2024.8.0
  • Deployment: docker compose

Akumatic avatar Sep 06 '24 00:09 Akumatic

instead of just setting the environment variables to the file path, you need to tell authentik that it's a file path by prefixing it with file://

BeryJu avatar Sep 07 '24 19:09 BeryJu

hi, i am having the same issue,

the secret file is of course also defined on a top-level 'secrets' element in the compose file

where are you suggesting we should put the "file://" part?

Tnx Koen

KoenWindey avatar Sep 26 '24 15:09 KoenWindey

where are you suggesting we should put the "file://" part?

in front of the file path, e.g. AUTHENTIK_EMAIL__PASSWORD: file:///run/secrets/mail_pass

This is actually in the documentation under “Installation > Configuration”, perhaps I missed it when I first read it.

While the issue itself is solved, it might be useful to include a hint about secrets directly on the Docker Compose installation page

Akumatic avatar Sep 26 '24 17:09 Akumatic

Mmm - yes, indeed. However, I'm still having issues due to file permissions. Since my secrets are saved in a folder for only root access, it seems that authentik cannot read the file...

KoenWindey avatar Sep 27 '24 04:09 KoenWindey

You can change the permissions for the secrets files mounted here: https://docs.docker.com/reference/compose-file/services/#long-syntax-4, although the default mode is 0444 which should work just fine

BeryJu avatar Oct 31 '24 17:10 BeryJu