Files
miti99bot/aws
tiennm99 0502ea28d2 fix(ci): pin deploy role ARN for OIDC auth
The deploy workflow no longer relies on a missing AWS_ACCOUNT_ID secret,
preventing invalid assume-role ARNs and matching the repo's documented AWS setup.
2026-05-15 22:36:15 +07:00
..

AWS account setup

One-time setup steps for a fresh AWS account. After this is done, every push to main deploys via GitHub Actions OIDC; no human-in-loop AWS commands needed.

For the full onboarding walkthrough (prerequisites, Telegram wiring, cost guardrails), see ../docs/deploy-aws-free-tier-guide.md. This file is the condensed cheatsheet.

Region: ap-southeast-1 (Singapore). Change in samconfig.toml if needed. Stack name: miti99bot. Change in samconfig.toml.


1. AWS account hygiene

  1. Enable MFA on the root user.
  2. Create an IAM admin user admin (CLI access keys). Use only for the first sam deploy --guided.
  3. Set CLI default region:
    aws configure set region ap-southeast-1 --profile admin
    aws configure set aws_access_key_id  AKIA…  --profile admin
    aws configure set aws_secret_access_key …   --profile admin
    

2. SSM Parameter Store secrets

Create the four required secrets. Names must match template.yaml (/miti99bot/${StackEnv}/…).

aws ssm put-parameter --name /miti99bot/prod/telegram-bot-token \
    --value "<bot-father-token>" --type SecureString --profile admin

aws ssm put-parameter --name /miti99bot/prod/telegram-webhook-secret \
    --value "$(openssl rand -hex 32)" --type SecureString --profile admin

aws ssm put-parameter --name /miti99bot/prod/gemini-api-key \
    --value "<google-ai-studio-key>" --type SecureString --profile admin

aws ssm put-parameter --name /miti99bot/prod/cron-shared-secret \
    --value "$(openssl rand -hex 32)" --type SecureString --profile admin

Save the webhook + cron secrets locally — you'll set them on the Telegram side and on the EventBridge schedule headers.

3. GitHub OIDC identity provider

One-time per AWS account:

aws iam create-open-id-connect-provider \
  --url https://token.actions.githubusercontent.com \
  --client-id-list sts.amazonaws.com \
  --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 \
  --profile admin

(GitHub publishes the canonical thumbprint; verify on docs.github.com if rotated.)

4. Deploy IAM role for GitHub Actions

Edit aws/iam-github-oidc-trust.json if you are changing the AWS account or GitHub repo. This repo is already prefilled for account 225603493174 and tiennm99/miti99bot. If you change accounts, update .github/workflows/deploy.yml to match the same role ARN, then:

aws iam create-role \
  --role-name github-deploy-miti99bot \
  --assume-role-policy-document file://aws/iam-github-oidc-trust.json \
  --profile admin

# Permissions (broad to start; tighten with stack-scoped policies later).
for arn in \
  arn:aws:iam::aws:policy/AWSCloudFormationFullAccess \
  arn:aws:iam::aws:policy/AWSLambda_FullAccess \
  arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess \
  arn:aws:iam::aws:policy/AmazonEventBridgeFullAccess \
  arn:aws:iam::aws:policy/AmazonSQSFullAccess \
  arn:aws:iam::aws:policy/AmazonSSMFullAccess \
  arn:aws:iam::aws:policy/CloudWatchLogsFullAccess \
  arn:aws:iam::aws:policy/AWSBudgetsActionsWithAWSResourceControlAccess \
  arn:aws:iam::aws:policy/IAMFullAccess \
  arn:aws:iam::aws:policy/AmazonS3FullAccess; do
  aws iam attach-role-policy --role-name github-deploy-miti99bot \
    --policy-arn "$arn" --profile admin
done

Yes, this is broad. SAM creates IAM roles for the Lambda, so the deploy role needs iam:CreateRole. Tighten later with custom policies scoped to the stack's resource ARNs.

5. Add GitHub repo secrets

In GitHub repo settings → Secrets and variables → Actions:

Secret Value
ALERT_EMAIL (optional) Email for the $1 budget alert

The deploy workflow now uses the repo's fixed AWS account ID directly for the OIDC role ARN, so AWS_ACCOUNT_ID no longer needs to be stored in GitHub.

6. First deploy (manual)

make build-lambda
AWS_PROFILE=admin sam deploy --template-file template.yaml --guided

Confirm:

  • Stack name: miti99bot
  • Region: ap-southeast-1
  • Capabilities: CAPABILITY_IAM
  • Save to samconfig.toml: yes (already committed; this just confirms)

After CREATE_COMPLETE:

aws cloudformation describe-stacks --stack-name miti99bot \
  --query "Stacks[0].Outputs" --output table --profile admin

Note the FunctionUrl — point the Telegram webhook at it (see ../docs/deploy-aws-free-tier-guide.md Step 5).

Once the first deploy succeeds:

  1. Rotate / delete admin CLI keys (use only via console for emergencies).
  2. Trigger a workflow_dispatch deploy via GH Actions to confirm OIDC path works without the bootstrap user.
  3. Replace the broad managed policies on github-deploy-miti99bot with stack-scoped custom policies.

Lambda Web Adapter layer ARN

Pinned in template.yaml parameter LambdaAdapterLayerArn. Bump by checking:

Cost expectations

After the stack is up but idle, monthly cost should be $0. If you ever see >$0.01 in Cost Explorer, investigate — most likely culprits: CloudWatch Logs ingestion volume, DynamoDB writes from a runaway loop, or accidental egress past the 100 GB free tier.