stages/email: add helper for AWS-specific smtp password handling
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
bc6706016b
commit
c1b4c785c2
|
@ -82,7 +82,7 @@ from authentik.flows.views.executor import QS_KEY_TOKEN
|
|||
from authentik.lib.config import CONFIG
|
||||
from authentik.stages.email.models import EmailStage
|
||||
from authentik.stages.email.tasks import send_mails
|
||||
from authentik.stages.email.utils import TemplateEmailMessage
|
||||
from authentik.stages.email.utils.template import TemplateEmailMessage
|
||||
from authentik.tenants.models import Tenant
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
|
|
@ -39,7 +39,7 @@ from authentik.lib.sentry import SentryIgnoredException
|
|||
from authentik.lib.utils.http import get_client_ip, get_http_session
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.policies.models import PolicyBindingModel
|
||||
from authentik.stages.email.utils import TemplateEmailMessage
|
||||
from authentik.stages.email.utils.template import TemplateEmailMessage
|
||||
from authentik.tenants.models import Tenant
|
||||
from authentik.tenants.utils import DEFAULT_TENANT
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.core.management.base import BaseCommand, no_translations
|
|||
|
||||
from authentik.stages.email.models import EmailStage
|
||||
from authentik.stages.email.tasks import send_mail
|
||||
from authentik.stages.email.utils import TemplateEmailMessage
|
||||
from authentik.stages.email.utils.template import TemplateEmailMessage
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
|
|
@ -14,6 +14,7 @@ from structlog.stdlib import get_logger
|
|||
|
||||
from authentik.flows.models import Stage
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.stages.email.utils.aws import aws_calculate_password
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
@ -106,11 +107,17 @@ class EmailStage(Stage):
|
|||
"""Get fully configured Email Backend instance"""
|
||||
if self.use_global_settings:
|
||||
CONFIG.refresh("email.password")
|
||||
host = CONFIG.get("email.host")
|
||||
password = CONFIG.get("email.password")
|
||||
# Special case for AWS Email passwords
|
||||
if host.endswith("amazonaws.com"):
|
||||
region = host.replace(".amazonaws.com", "").split(".")[-1]
|
||||
password = aws_calculate_password(password, region)
|
||||
return self.backend_class(
|
||||
host=CONFIG.get("email.host"),
|
||||
host=host,
|
||||
port=CONFIG.get_int("email.port"),
|
||||
username=CONFIG.get("email.username"),
|
||||
password=CONFIG.get("email.password"),
|
||||
password=password,
|
||||
use_tls=CONFIG.get_bool("email.use_tls", False),
|
||||
use_ssl=CONFIG.get_bool("email.use_ssl", False),
|
||||
timeout=CONFIG.get_int("email.timeout"),
|
||||
|
|
|
@ -18,7 +18,7 @@ from authentik.flows.stage import ChallengeStageView
|
|||
from authentik.flows.views.executor import QS_KEY_TOKEN
|
||||
from authentik.stages.email.models import EmailStage
|
||||
from authentik.stages.email.tasks import send_mails
|
||||
from authentik.stages.email.utils import TemplateEmailMessage
|
||||
from authentik.stages.email.utils.template import TemplateEmailMessage
|
||||
|
||||
PLAN_CONTEXT_EMAIL_SENT = "email_sent"
|
||||
PLAN_CONTEXT_EMAIL_OVERRIDE = "email"
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
"""AWS Helpers"""
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
|
||||
# These values are required to calculate the signature. Do not change them.
|
||||
AWS_DATE = "11111111"
|
||||
AWS_SERVICE = "ses"
|
||||
AWS_MESSAGE = "SendRawEmail"
|
||||
AWS_TERMINAL = "aws4_request"
|
||||
AWS_VERSION = 0x04
|
||||
|
||||
|
||||
# https://docs.aws.amazon.com/ses/latest/dg/smtp-credentials.html#smtp-credentials-convert
|
||||
|
||||
|
||||
def aws_sign(key: bytes, msg: bytes) -> bytes:
|
||||
"""Hmac sign"""
|
||||
return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest()
|
||||
|
||||
|
||||
def aws_calculate_password(secret_access_key: str, region: str) -> str:
|
||||
"""Calculate AWS SMTP password from secret key"""
|
||||
signature = aws_sign(("AWS4" + secret_access_key).encode("utf-8"), AWS_DATE)
|
||||
signature = aws_sign(signature, region)
|
||||
signature = aws_sign(signature, AWS_SERVICE)
|
||||
signature = aws_sign(signature, AWS_TERMINAL)
|
||||
signature = aws_sign(signature, AWS_MESSAGE)
|
||||
signature_and_version = bytes([AWS_VERSION]) + signature
|
||||
smtp_password = base64.b64encode(signature_and_version)
|
||||
return smtp_password.decode("utf-8")
|
Reference in New Issue