#!/bin/bash # awsses_lambda_global.sh - SES Setup mit S3 + Global Lambda Shim -> SQS # Dieses Skript ist idempotent: Es kann sicher mehrfach ausgeführt werden. # Globale Lambda für alle Domains. set -e # --- CHECKS --- if ! command -v jq &> /dev/null; then echo "Fehler: 'jq' fehlt."; exit 1; fi if [ -z "$DOMAIN_NAME" ]; then echo "Fehler: DOMAIN_NAME ist nicht gesetzt."; exit 1; fi # Prüfen ob Python Code da ist PYTHON_FILE="ses_sns_shim_global.py" if [ ! -f "$PYTHON_FILE" ]; then echo "Fehler: $PYTHON_FILE nicht gefunden!" exit 1 fi # --- VARIABLEN --- AWS_REGION=${AWS_REGION:-"us-east-2"} EMAIL_PREFIX=${EMAIL_PREFIX:-""} CONFIGURATION_SET_NAME="relay-outbound" # Bucket Name generieren falls leer if [ -z "$S3_BUCKET_NAME" ]; then S3_BUCKET_NAME=$(echo "$DOMAIN_NAME" | tr '.' '-' | awk '{print $0 "-emails"}') fi # Namen (Global Lambda!) RULE_SET_NAME="bizmatch-ruleset" RULE_NAME="store-${DOMAIN_NAME//./-}-to-s3" QUEUE_NAME="${DOMAIN_NAME//./-}-queue" LAMBDA_NAME="ses-shim-global" LAMBDA_ROLE_NAME="SesShimGlobalRole" echo "==========================================================" echo " SES Setup (S3 -> Global Lambda Shim -> SQS) für $DOMAIN_NAME" echo "==========================================================" # --------------------------------------------------------- # 1. SES Identity & Config Set # --------------------------------------------------------- echo "[1/6] SES Identity Setup..." if ! aws sesv2 get-email-identity --email-identity ${DOMAIN_NAME} --region ${AWS_REGION} >/dev/null 2>&1; then aws sesv2 create-email-identity --email-identity ${DOMAIN_NAME} --region ${AWS_REGION} >/dev/null fi # Update Attributes (Idempotent) aws sesv2 put-email-identity-dkim-attributes --email-identity ${DOMAIN_NAME} --signing-enabled --region ${AWS_REGION} aws sesv2 put-email-identity-mail-from-attributes --email-identity ${DOMAIN_NAME} --mail-from-domain "mail.${DOMAIN_NAME}" --behavior-on-mx-failure USE_DEFAULT_VALUE --region ${AWS_REGION} aws sesv2 put-email-identity-configuration-set-attributes --email-identity ${DOMAIN_NAME} --configuration-set-name "$CONFIGURATION_SET_NAME" --region ${AWS_REGION} # --------------------------------------------------------- # 2. SQS Queue holen (nur zur Validierung, Lambda holt dynamisch) # --------------------------------------------------------- echo "[2/6] Queue URL ermitteln (zur Validierung)..." QUEUE_URL=$(aws sqs get-queue-url --queue-name "$QUEUE_NAME" --region "$AWS_REGION" --output text --query 'QueueUrl' 2>/dev/null) if [ -z "$QUEUE_URL" ]; then echo "FEHLER: Queue $QUEUE_NAME nicht gefunden! ./create-queue.sh zuerst ausführen."; exit 1; fi QUEUE_ARN=$(aws sqs get-queue-attributes --queue-url "$QUEUE_URL" --attribute-names QueueArn --region "$AWS_REGION" --output text --query 'Attributes.QueueArn') # --------------------------------------------------------- # 3. IAM Role für Global Lambda erstellen # --------------------------------------------------------- echo "[3/6] IAM Role für Lambda prüfen/erstellen..." TRUST_POLICY='{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"Service": "lambda.amazonaws.com"},"Action": "sts:AssumeRole"}]}' if ! aws iam get-role --role-name "$LAMBDA_ROLE_NAME" >/dev/null 2>&1; then aws iam create-role --role-name "$LAMBDA_ROLE_NAME" --assume-role-policy-document "$TRUST_POLICY" >/dev/null echo " -> Rolle erstellt." else echo " -> Rolle existiert bereits." fi # Permissions Policy (Lambda darf Logs schreiben und in ALLE Queues mit *-queue senden) LAMBDA_POLICY=$(jq -n '{ Version: "2012-10-17", Statement: [ { Effect: "Allow", Action: ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"], Resource: "arn:aws:logs:*:*:*" }, { Effect: "Allow", Action: "sqs:SendMessage", Resource: "arn:aws:sqs:*:*:*-queue" }, { Effect: "Allow", Action: "sqs:GetQueueUrl", Resource: "*" } ] }' | jq -c .) aws iam put-role-policy --role-name "$LAMBDA_ROLE_NAME" --policy-name "SesShimGlobalPermissions" --policy-document "$LAMBDA_POLICY" echo " -> Permissions aktualisiert." # Kurze Pause für IAM Propagation, falls Rolle neu war sleep 5 # --------------------------------------------------------- # 4. Lambda Funktion erstellen/updaten (Global!) # --------------------------------------------------------- echo "[4/6] Global Lambda Shim deployen..." # Zip erstellen cp "$PYTHON_FILE" lambda_function.py zip -q lambda.zip lambda_function.py # Keine Env-Vars nötig, da dynamisch ROLE_ARN=$(aws iam get-role --role-name "$LAMBDA_ROLE_NAME" --query 'Role.Arn' --output text) if ! aws lambda get-function --function-name "$LAMBDA_NAME" --region "$AWS_REGION" >/dev/null 2>&1; then echo " -> Erstelle neue Lambda-Funktion..." aws lambda create-function --function-name "$LAMBDA_NAME" \ --runtime python3.11 --handler lambda_function.lambda_handler \ --role "$ROLE_ARN" --zip-file fileb://lambda.zip \ --region "$AWS_REGION" >/dev/null else echo " -> Aktualisiere existierende Lambda-Funktion..." aws lambda update-function-code --function-name "$LAMBDA_NAME" --zip-file fileb://lambda.zip --region "$AWS_REGION" >/dev/null # Warte kurz sleep 2 aws lambda update-function-configuration --function-name "$LAMBDA_NAME" --region "$AWS_REGION" >/dev/null fi # Aufräumen rm lambda.zip lambda_function.py # --------------------------------------------------------- # 5. Permission: SES darf Lambda aufrufen (Global, einmalig) # --------------------------------------------------------- echo "[5/6] SES Permission für Lambda..." aws lambda add-permission --function-name "$LAMBDA_NAME" \ --statement-id "AllowSESInvoke-Global" \ --action "lambda:InvokeFunction" \ --principal "ses.amazonaws.com" \ --region "$AWS_REGION" 2>/dev/null || true # --------------------------------------------------------- # 6. SES Rule (S3 + Global Lambda) # --------------------------------------------------------- echo "[6/6] SES Receipt Rule (S3 + Lambda) konfigurieren..." LAMBDA_ARN=$(aws lambda get-function --function-name "$LAMBDA_NAME" --region "$AWS_REGION" --query 'Configuration.FunctionArn' --output text) # Rule Set prüfen if ! aws ses list-receipt-rule-sets --region ${AWS_REGION} | grep -q "bizmatch-ruleset"; then aws ses create-receipt-rule-set --rule-set-name "bizmatch-ruleset" --region ${AWS_REGION} fi # Regel-Definition RULE_JSON=$(jq -n \ --arg bucket "$S3_BUCKET_NAME" \ --arg prefix "$EMAIL_PREFIX" \ --arg larn "$LAMBDA_ARN" \ --arg rule "$RULE_NAME" \ --arg domain "$DOMAIN_NAME" \ --arg subdomain "mail.$DOMAIN_NAME" \ '{ Name: $rule, Enabled: true, ScanEnabled: true, TlsPolicy: "Require", Recipients: [$domain, $subdomain], Actions: [ { S3Action: { BucketName: $bucket, ObjectKeyPrefix: $prefix } }, { LambdaAction: { FunctionArn: $larn, InvocationType: "Event" } } ] }') # Check ob Regel existiert -> Update, sonst Create if aws ses describe-receipt-rule --rule-set-name "bizmatch-ruleset" --rule-name "$RULE_NAME" --region "$AWS_REGION" >/dev/null 2>&1; then echo " -> Aktualisiere existierende Regel..." aws ses update-receipt-rule --rule-set-name "bizmatch-ruleset" --rule "$RULE_JSON" --region "$AWS_REGION" else echo " -> Erstelle neue Regel..." aws ses create-receipt-rule --rule-set-name "bizmatch-ruleset" --rule "$RULE_JSON" --region "$AWS_REGION" fi # Aktivieren aws ses set-active-receipt-rule-set --rule-set-name "bizmatch-ruleset" --region ${AWS_REGION} echo "========================================================" echo "✅ Setup erfolgreich. Globale Lambda ($LAMBDA_NAME) für alle Domains." echo " S3 -> Lambda -> Domain-spezifische SQS" echo "========================================================"