From cf9b7188e398d4d97b11b29d5f3e31de1c5ece02 Mon Sep 17 00:00:00 2001 From: lakshayman Date: Fri, 2 Jan 2026 09:26:35 +0530 Subject: [PATCH 1/6] fix: pipeline --- .github/workflows/pipeline.yaml | 40 +++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pipeline.yaml b/.github/workflows/pipeline.yaml index bd7eb37..bbe9455 100644 --- a/.github/workflows/pipeline.yaml +++ b/.github/workflows/pipeline.yaml @@ -14,13 +14,13 @@ jobs: name: Prepare runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Inject slug/short variables - uses: rlespinasse/github-slug-action@v3.x + uses: rlespinasse/github-slug-action@v5 - name: Prepare Outputs id: prepare-step run: | - echo "::set-output name=branch_name::${GITHUB_REF_SLUG}"; + echo "branch_name=${GITHUB_REF_SLUG}" >> $GITHUB_OUTPUT outputs: branch_name: ${{ steps.prepare-step.outputs.branch_name }} @@ -29,13 +29,19 @@ jobs: runs-on: ubuntu-latest environment: ${{ needs.prepare.outputs.branch_name }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: '1.25.1' - - uses: actions/setup-python@v2 - - uses: aws-actions/setup-sam@v1 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.11' + - name: Setup SAM CLI + uses: aws-actions/setup-sam@v2 + with: + use-installer: true - name: Build resources run: sam build --template ${SAM_TEMPLATE} @@ -46,7 +52,7 @@ jobs: PIPELINE_USER_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} PIPELINE_EXECUTION_ROLE: ${{ secrets.PIPELINE_EXECUTION_ROLE }} REGION: ${{ secrets.REGION }} - uses: aws-actions/configure-aws-credentials@v1 + uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ env.PIPELINE_USER_ACCESS_KEY_ID }} aws-secret-access-key: ${{ env.PIPELINE_USER_SECRET_ACCESS_KEY }} @@ -65,7 +71,7 @@ jobs: --s3-bucket ${ARTIFACTS_BUCKET} \ --region ${REGION} \ --output-template-file packaged.yaml - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v6 with: name: packaged.yaml path: packaged.yaml @@ -75,10 +81,16 @@ jobs: runs-on: ubuntu-latest environment: ${{ needs.prepare.outputs.branch_name }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v2 - - uses: aws-actions/setup-sam@v1 - - uses: actions/download-artifact@v4 + - uses: actions/checkout@v5 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.11' + - name: Setup SAM CLI + uses: aws-actions/setup-sam@v2 + with: + use-installer: true + - uses: actions/download-artifact@v6 with: name: packaged.yaml @@ -88,7 +100,7 @@ jobs: PIPELINE_USER_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} PIPELINE_EXECUTION_ROLE: ${{ secrets.PIPELINE_EXECUTION_ROLE }} REGION: ${{ secrets.REGION }} - uses: aws-actions/configure-aws-credentials@v1 + uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ env.PIPELINE_USER_ACCESS_KEY_ID }} aws-secret-access-key: ${{ env.PIPELINE_USER_SECRET_ACCESS_KEY }} From 5295089b66f6fc2f01ba199fa64b33f64d23b84b Mon Sep 17 00:00:00 2001 From: lakshayman Date: Fri, 2 Jan 2026 09:29:23 +0530 Subject: [PATCH 2/6] fix: added policies in template instead of adding manually --- template.yaml | 118 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 3 deletions(-) diff --git a/template.yaml b/template.yaml index a984bcb..652fbb6 100644 --- a/template.yaml +++ b/template.yaml @@ -87,6 +87,9 @@ Resources: - x86_64 Layers: - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: requestLimit Events: Preflight: Type: Api @@ -105,7 +108,18 @@ Resources: Architectures: - x86_64 Layers: - - !Ref SharedLayer + - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: featureFlag + - DynamoDBCrudPolicy: + TableName: featureFlagUserMapping + - DynamoDBCrudPolicy: + TableName: requestLimit + - SSMParameterReadPolicy: + ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY + - SSMParameterReadPolicy: + ParameterName: STAGING_RDS_BACKEND_PUBLIC_KEY Events: CatchAll: Type: Api @@ -124,7 +138,14 @@ Resources: Architectures: - x86_64 Layers: - - !Ref SharedLayer + - !Ref SharedLayer + Policies: + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - lambda:PutFunctionConcurrency + Resource: '*' Events: CatchAll: Type: Api @@ -143,7 +164,10 @@ Resources: Architectures: - x86_64 Layers: - - !Ref SharedLayer + - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: requestLimit Events: CatchAll: Type: Api @@ -163,6 +187,17 @@ Resources: - x86_64 Layers: - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: featureFlag + - DynamoDBCrudPolicy: + TableName: featureFlagUserMapping + - DynamoDBCrudPolicy: + TableName: requestLimit + - SSMParameterReadPolicy: + ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY + - SSMParameterReadPolicy: + ParameterName: STAGING_RDS_BACKEND_PUBLIC_KEY Events: CatchAll: Type: Api @@ -182,6 +217,17 @@ Resources: - x86_64 Layers: - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: featureFlag + - DynamoDBCrudPolicy: + TableName: featureFlagUserMapping + - DynamoDBCrudPolicy: + TableName: requestLimit + - SSMParameterReadPolicy: + ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY + - SSMParameterReadPolicy: + ParameterName: STAGING_RDS_BACKEND_PUBLIC_KEY Events: CatchAll: Type: Api @@ -201,6 +247,17 @@ Resources: - x86_64 Layers: - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: featureFlag + - DynamoDBCrudPolicy: + TableName: featureFlagUserMapping + - DynamoDBCrudPolicy: + TableName: requestLimit + - SSMParameterReadPolicy: + ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY + - SSMParameterReadPolicy: + ParameterName: STAGING_RDS_BACKEND_PUBLIC_KEY Events: CatchAll: Type: Api @@ -220,6 +277,17 @@ Resources: - x86_64 Layers: - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: featureFlag + - DynamoDBCrudPolicy: + TableName: featureFlagUserMapping + - DynamoDBCrudPolicy: + TableName: requestLimit + - SSMParameterReadPolicy: + ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY + - SSMParameterReadPolicy: + ParameterName: STAGING_RDS_BACKEND_PUBLIC_KEY Events: CatchAll: Type: Api @@ -239,6 +307,17 @@ Resources: - x86_64 Layers: - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: featureFlag + - DynamoDBCrudPolicy: + TableName: featureFlagUserMapping + - DynamoDBCrudPolicy: + TableName: requestLimit + - SSMParameterReadPolicy: + ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY + - SSMParameterReadPolicy: + ParameterName: STAGING_RDS_BACKEND_PUBLIC_KEY Events: CatchAll: Type: Api @@ -258,6 +337,17 @@ Resources: - x86_64 Layers: - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: featureFlag + - DynamoDBCrudPolicy: + TableName: featureFlagUserMapping + - DynamoDBCrudPolicy: + TableName: requestLimit + - SSMParameterReadPolicy: + ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY + - SSMParameterReadPolicy: + ParameterName: STAGING_RDS_BACKEND_PUBLIC_KEY Events: CatchAll: Type: Api @@ -277,6 +367,17 @@ Resources: - x86_64 Layers: - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: featureFlag + - DynamoDBCrudPolicy: + TableName: featureFlagUserMapping + - DynamoDBCrudPolicy: + TableName: requestLimit + - SSMParameterReadPolicy: + ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY + - SSMParameterReadPolicy: + ParameterName: STAGING_RDS_BACKEND_PUBLIC_KEY Events: CatchAll: Type: Api @@ -296,6 +397,17 @@ Resources: - x86_64 Layers: - !Ref SharedLayer + Policies: + - DynamoDBCrudPolicy: + TableName: featureFlag + - DynamoDBCrudPolicy: + TableName: featureFlagUserMapping + - DynamoDBCrudPolicy: + TableName: requestLimit + - SSMParameterReadPolicy: + ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY + - SSMParameterReadPolicy: + ParameterName: STAGING_RDS_BACKEND_PUBLIC_KEY Events: CatchAll: Type: Api From 9cb024b3bb25497511c0f98515164a76487118e4 Mon Sep 17 00:00:00 2001 From: lakshayman Date: Fri, 2 Jan 2026 09:32:50 +0530 Subject: [PATCH 3/6] chore: added setup dynamo table script and POST_DEPLOYMENT_SETUP --- POST_DEPLOYMENT_SETUP.md | 228 +++++++++++++++++++++++++++++++++++++++ setup-dynamodb-tables.sh | 98 +++++++++++++++++ 2 files changed, 326 insertions(+) create mode 100644 POST_DEPLOYMENT_SETUP.md create mode 100755 setup-dynamodb-tables.sh diff --git a/POST_DEPLOYMENT_SETUP.md b/POST_DEPLOYMENT_SETUP.md new file mode 100644 index 0000000..45f4cab --- /dev/null +++ b/POST_DEPLOYMENT_SETUP.md @@ -0,0 +1,228 @@ +# Post-Deployment Setup Guide + +After deploying with `sam deploy`, you need to set up the following resources: + +## ๐Ÿ”ด Critical: DynamoDB Tables + +The error you're seeing is because **DynamoDB tables don't exist**. You need to create 3 tables: + +### Quick Setup (Using Script) + +```bash +# Make script executable +chmod +x setup-dynamodb-tables.sh + +# Run the script (defaults to us-east-1) +./setup-dynamodb-tables.sh + +# OR specify a region +./setup-dynamodb-tables.sh us-east-1 +``` + +### Manual Setup + +#### 1. Create `featureFlag` Table + +```bash +aws dynamodb create-table \ + --table-name featureFlag \ + --attribute-definitions AttributeName=id,AttributeType=S \ + --key-schema AttributeName=id,KeyType=HASH \ + --billing-mode PAY_PER_REQUEST \ + --region us-east-1 +``` + +#### 2. Create `featureFlagUserMapping` Table + +```bash +aws dynamodb create-table \ + --table-name featureFlagUserMapping \ + --attribute-definitions \ + AttributeName=userId,AttributeType=S \ + AttributeName=flagId,AttributeType=S \ + --key-schema \ + AttributeName=userId,KeyType=HASH \ + AttributeName=flagId,KeyType=RANGE \ + --billing-mode PAY_PER_REQUEST \ + --region us-east-1 +``` + +#### 3. Create `requestLimit` Table (This is the missing one causing your error!) + +```bash +aws dynamodb create-table \ + --table-name requestLimit \ + --attribute-definitions AttributeName=limitType,AttributeType=S \ + --key-schema AttributeName=limitType,KeyType=HASH \ + --billing-mode PAY_PER_REQUEST \ + --region us-east-1 +``` + +#### 4. Initialize `requestLimit` Table + +After creating the table, you need to add an initial value: + +```bash +aws dynamodb put-item \ + --table-name requestLimit \ + --item '{ + "limitType": {"S": "pendingLimit"}, + "limitValue": {"N": "1000"} + }' \ + --region us-east-1 +``` + +--- + +## โœ… Verify Tables Exist + +```bash +# List all tables +aws dynamodb list-tables --region us-east-1 + +# Check specific table +aws dynamodb describe-table --table-name requestLimit --region us-east-1 +``` + +You should see: +- `featureFlag` +- `featureFlagUserMapping` +- `requestLimit` + +--- + +## ๐Ÿ”‘ SSM Parameter for JWT Public Key + +Make sure the JWT public key exists in AWS Systems Manager Parameter Store: + +### For PRODUCTION: + +```bash +# Check if parameter exists +aws ssm get-parameter \ + --name PROD_RDS_BACKEND_PUBLIC_KEY \ + --with-decryption \ + --region us-east-1 + +# If it doesn't exist, create it: +aws ssm put-parameter \ + --name PROD_RDS_BACKEND_PUBLIC_KEY \ + --value "-----BEGIN PUBLIC KEY----- +YOUR_PUBLIC_KEY_HERE +-----END PUBLIC KEY-----" \ + --type SecureString \ + --region us-east-1 +``` + +### For DEVELOPMENT: + +```bash +# Check if parameter exists +aws ssm get-parameter \ + --name STAGING_RDS_BACKEND_PUBLIC_KEY \ + --with-decryption \ + --region us-east-1 + +# If it doesn't exist, create it: +aws ssm put-parameter \ + --name STAGING_RDS_BACKEND_PUBLIC_KEY \ + --value "-----BEGIN PUBLIC KEY----- +YOUR_PUBLIC_KEY_HERE +-----END PUBLIC KEY-----" \ + --type SecureString \ + --region us-east-1 +``` + +--- + +## ๐Ÿงช Test After Setup + +After creating the tables, test your API: + +```bash +# 1. Health check (should work) +curl https://j31g91e2fa.execute-api.us-east-1.amazonaws.com/Prod/health-check + +# 2. Get feature flags (should work now) +curl -X GET "https://j31g91e2fa.execute-api.us-east-1.amazonaws.com/Prod/feature-flags/" \ + -H "Cookie: rds-session-staging=YOUR_JWT_TOKEN" \ + -H "Origin: https://test.realdevsquad.com" +``` + +--- + +## ๐Ÿ“‹ Complete Checklist + +- [ ] **DynamoDB Tables Created:** + - [ ] `featureFlag` table exists + - [ ] `featureFlagUserMapping` table exists + - [ ] `requestLimit` table exists + - [ ] `requestLimit` table has initial item with `limitType: "pendingLimit"` and `limitValue: 1000` + +- [ ] **SSM Parameter:** + - [ ] `PROD_RDS_BACKEND_PUBLIC_KEY` exists (for PRODUCTION) + - [ ] OR `STAGING_RDS_BACKEND_PUBLIC_KEY` exists (for DEVELOPMENT) + +- [ ] **Testing:** + - [ ] Health check endpoint works + - [ ] Feature flags endpoints work with JWT token + +--- + +## ๐Ÿ” Troubleshooting + +### Error: "ResourceNotFoundException: Requested resource not found" + +**Cause:** DynamoDB table doesn't exist + +**Solution:** Create the missing table using the commands above + +### Error: "invalid memory address or nil pointer dereference" + +**Cause:** Code is trying to unmarshal a nil response from DynamoDB (table doesn't exist or item doesn't exist) + +**Solution:** +1. Create the `requestLimit` table +2. Initialize it with the default value (see step 4 above) + +### Error: "ParameterNotFound" when calling API + +**Cause:** SSM Parameter for JWT public key doesn't exist + +**Solution:** Create the SSM parameter with the public key (see SSM Parameter section above) + +### Error: "AccessDeniedException" when creating tables + +**Cause:** Your AWS credentials don't have DynamoDB permissions + +**Solution:** Ensure your AWS user/role has: +- `dynamodb:CreateTable` +- `dynamodb:PutItem` +- `dynamodb:DescribeTable` +- `dynamodb:ListTables` + +--- + +## ๐Ÿš€ Quick Setup Command + +Run this to set up everything: + +```bash +# 1. Create all tables +./setup-dynamodb-tables.sh us-east-1 + +# 2. Verify tables +aws dynamodb list-tables --region us-east-1 + +# 3. Test API +curl https://j31g91e2fa.execute-api.us-east-1.amazonaws.com/Prod/health-check +``` + +--- + +## ๐Ÿ“ Notes + +- Tables are created with **PAY_PER_REQUEST** billing mode (no capacity planning needed) +- The `requestLimit` table is initialized with a default value of 1000 +- You can adjust the initial `limitValue` based on your needs +- All tables are created in the same region as your Lambda functions diff --git a/setup-dynamodb-tables.sh b/setup-dynamodb-tables.sh new file mode 100755 index 0000000..6770cfd --- /dev/null +++ b/setup-dynamodb-tables.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# Script to create all required DynamoDB tables for feature-flag-backend +# Usage: ./setup-dynamodb-tables.sh [region] + +set -e + +REGION=${1:-us-east-1} + +echo "๐Ÿš€ Setting up DynamoDB tables in region: $REGION" +echo "" + +# Table 1: featureFlag +echo "Creating table: featureFlag" +aws dynamodb create-table \ + --table-name featureFlag \ + --attribute-definitions \ + AttributeName=id,AttributeType=S \ + --key-schema \ + AttributeName=id,KeyType=HASH \ + --billing-mode PAY_PER_REQUEST \ + --region $REGION \ + --no-cli-pager + +echo "โœ… Created featureFlag table" +echo "" + +# Table 2: featureFlagUserMapping +echo "Creating table: featureFlagUserMapping" +aws dynamodb create-table \ + --table-name featureFlagUserMapping \ + --attribute-definitions \ + AttributeName=userId,AttributeType=S \ + AttributeName=flagId,AttributeType=S \ + --key-schema \ + AttributeName=userId,KeyType=HASH \ + AttributeName=flagId,KeyType=RANGE \ + --billing-mode PAY_PER_REQUEST \ + --region $REGION \ + --no-cli-pager + +echo "โœ… Created featureFlagUserMapping table" +echo "" + +# Table 3: requestLimit +echo "Creating table: requestLimit" +aws dynamodb create-table \ + --table-name requestLimit \ + --attribute-definitions \ + AttributeName=limitType,AttributeType=S \ + --key-schema \ + AttributeName=limitType,KeyType=HASH \ + --billing-mode PAY_PER_REQUEST \ + --region $REGION \ + --no-cli-pager + +echo "โœ… Created requestLimit table" +echo "" + +# Wait for tables to be active +echo "โณ Waiting for tables to become active..." +aws dynamodb wait table-exists \ + --table-name featureFlag \ + --region $REGION + +aws dynamodb wait table-exists \ + --table-name featureFlagUserMapping \ + --region $REGION + +aws dynamodb wait table-exists \ + --table-name requestLimit \ + --region $REGION + +echo "โœ… All tables are active!" +echo "" + +# Initialize requestLimit table with default value +echo "Initializing requestLimit table with default value..." +aws dynamodb put-item \ + --table-name requestLimit \ + --item '{ + "limitType": {"S": "pendingLimit"}, + "limitValue": {"N": "1000"} + }' \ + --region $REGION \ + --no-cli-pager + +echo "โœ… Initialized requestLimit with default value (1000)" +echo "" + +echo "๐ŸŽ‰ All DynamoDB tables created and initialized successfully!" +echo "" +echo "Tables created:" +echo " - featureFlag" +echo " - featureFlagUserMapping" +echo " - requestLimit (with initial value)" +echo "" +echo "You can now test your API endpoints!" From a978723159303b58eb07a9eba7e9da53a9563962 Mon Sep 17 00:00:00 2001 From: lakshayman Date: Fri, 2 Jan 2026 10:35:27 +0530 Subject: [PATCH 4/6] chore: remove trailing spaces from public key if any --- layer/jwt/jwt.go | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/layer/jwt/jwt.go b/layer/jwt/jwt.go index a7ab0d9..a765a29 100644 --- a/layer/jwt/jwt.go +++ b/layer/jwt/jwt.go @@ -85,26 +85,33 @@ func (j *JWTUtils) initialize() error { } } + log.Printf("Attempting to fetch public key from SSM parameter: %s (Environment: %s)", parameterName, envConfig.Environment) publicKeyString, err := getPublicKeyFromParameterStore(parameterName) if err != nil { + log.Printf("Failed to get public key from SSM: %v", err) return err } - + publicKeyString = strings.TrimSpace(publicKeyString) + block, _ := pem.Decode([]byte(publicKeyString)) if block == nil { + log.Printf("Failed to decode PEM block from public key. First 100 chars: %s", publicKeyString[:min(100, len(publicKeyString))]) return errors.New("internal server error") } pub, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { + log.Printf("Failed to parse PKIX public key: %v", err) return fmt.Errorf("internal server error") } rsaPublicKey, ok := pub.(*rsa.PublicKey) if !ok { + log.Printf("Public key is not an RSA public key") return errors.New("internal server error") } + log.Printf("Successfully initialized JWT utils with public key") j.publicKey = rsaPublicKey return nil } @@ -115,6 +122,7 @@ func getPublicKeyFromParameterStore(parameterName string) (string, error) { cfg, err := config.LoadDefaultConfig(ctx) if err != nil { + log.Printf("Failed to load AWS config: %v", err) return "", err } @@ -126,10 +134,24 @@ func getPublicKeyFromParameterStore(parameterName string) (string, error) { result, err := svc.GetParameter(ctx, input) if err != nil { + log.Printf("Failed to get parameter %s from SSM: %v", parameterName, err) return "", err } - return *result.Parameter.Value, nil + if result.Parameter == nil || result.Parameter.Value == nil { + log.Printf("Parameter %s exists but has no value", parameterName) + return "", errors.New("parameter has no value") + } + + value := strings.TrimSpace(*result.Parameter.Value) + return value, nil +} + +func min(a, b int) int { + if a < b { + return a + } + return b } func (j *JWTUtils) ValidateToken(tokenString string) (jwt.MapClaims, error) { From 0d995f497c20b8b194ab04654f2e46ea41707681 Mon Sep 17 00:00:00 2001 From: lakshayman Date: Fri, 16 Jan 2026 14:31:56 +0530 Subject: [PATCH 5/6] fix: resolve comments --- POST_DEPLOYMENT_SETUP.md | 12 ++-- samconfig.toml | 15 +++++ setup-dynamodb-tables.sh | 128 +++++++++++++++++++++++---------------- template.yaml | 120 +++++++++++++++++++++++++++++------- 4 files changed, 196 insertions(+), 79 deletions(-) create mode 100644 samconfig.toml diff --git a/POST_DEPLOYMENT_SETUP.md b/POST_DEPLOYMENT_SETUP.md index 45f4cab..5ea0ac0 100644 --- a/POST_DEPLOYMENT_SETUP.md +++ b/POST_DEPLOYMENT_SETUP.md @@ -139,12 +139,14 @@ YOUR_PUBLIC_KEY_HERE After creating the tables, test your API: +**Note:** Replace `{YOUR_API_GATEWAY_URL}` with your actual API Gateway endpoint URL. You can find it in the SAM deployment output or AWS Console. + ```bash # 1. Health check (should work) -curl https://j31g91e2fa.execute-api.us-east-1.amazonaws.com/Prod/health-check +curl https://{YOUR_API_GATEWAY_URL}/Prod/health-check # 2. Get feature flags (should work now) -curl -X GET "https://j31g91e2fa.execute-api.us-east-1.amazonaws.com/Prod/feature-flags/" \ +curl -X GET "https://{YOUR_API_GATEWAY_URL}/Prod/feature-flags/" \ -H "Cookie: rds-session-staging=YOUR_JWT_TOKEN" \ -H "Origin: https://test.realdevsquad.com" ``` @@ -181,7 +183,7 @@ curl -X GET "https://j31g91e2fa.execute-api.us-east-1.amazonaws.com/Prod/feature **Cause:** Code is trying to unmarshal a nil response from DynamoDB (table doesn't exist or item doesn't exist) -**Solution:** +**Solution:** 1. Create the `requestLimit` table 2. Initialize it with the default value (see step 4 above) @@ -214,8 +216,8 @@ Run this to set up everything: # 2. Verify tables aws dynamodb list-tables --region us-east-1 -# 3. Test API -curl https://j31g91e2fa.execute-api.us-east-1.amazonaws.com/Prod/health-check +# 3. Test API (replace {YOUR_API_GATEWAY_URL} with your actual endpoint) +curl https://{YOUR_API_GATEWAY_URL}/Prod/health-check ``` --- diff --git a/samconfig.toml b/samconfig.toml new file mode 100644 index 0000000..5b02e46 --- /dev/null +++ b/samconfig.toml @@ -0,0 +1,15 @@ +version = 0.1 + +[default.deploy.parameters] +stack_name = "feature-flag-2" +resolve_s3 = true +s3_prefix = "feature-flag-2" +region = "us-east-1" +confirm_changeset = true +capabilities = "CAPABILITY_IAM" +disable_rollback = true +parameter_overrides = "Environment=\"PRODUCTION\"" +image_repositories = [] + +[default.global.parameters] +region = "us-east-1" diff --git a/setup-dynamodb-tables.sh b/setup-dynamodb-tables.sh index 6770cfd..27c84fa 100755 --- a/setup-dynamodb-tables.sh +++ b/setup-dynamodb-tables.sh @@ -7,85 +7,111 @@ set -e REGION=${1:-us-east-1} +# Helper function to check if a table exists +table_exists() { + local table_name="$1" + aws dynamodb describe-table \ + --table-name "$table_name" \ + --region "$REGION" \ + --no-cli-pager >/dev/null 2>&1 +} + echo "๐Ÿš€ Setting up DynamoDB tables in region: $REGION" echo "" # Table 1: featureFlag -echo "Creating table: featureFlag" -aws dynamodb create-table \ - --table-name featureFlag \ - --attribute-definitions \ - AttributeName=id,AttributeType=S \ - --key-schema \ - AttributeName=id,KeyType=HASH \ - --billing-mode PAY_PER_REQUEST \ - --region $REGION \ - --no-cli-pager - -echo "โœ… Created featureFlag table" +if ! table_exists "featureFlag"; then + echo "Creating table: featureFlag" + aws dynamodb create-table \ + --table-name featureFlag \ + --attribute-definitions \ + AttributeName=id,AttributeType=S \ + --key-schema \ + AttributeName=id,KeyType=HASH \ + --billing-mode PAY_PER_REQUEST \ + --region "$REGION" \ + --no-cli-pager + echo "โœ… Created featureFlag table" +else + echo "โญ๏ธ Table featureFlag already exists, skipping creation" +fi echo "" # Table 2: featureFlagUserMapping -echo "Creating table: featureFlagUserMapping" -aws dynamodb create-table \ - --table-name featureFlagUserMapping \ - --attribute-definitions \ - AttributeName=userId,AttributeType=S \ - AttributeName=flagId,AttributeType=S \ - --key-schema \ - AttributeName=userId,KeyType=HASH \ - AttributeName=flagId,KeyType=RANGE \ - --billing-mode PAY_PER_REQUEST \ - --region $REGION \ - --no-cli-pager - -echo "โœ… Created featureFlagUserMapping table" +if ! table_exists "featureFlagUserMapping"; then + echo "Creating table: featureFlagUserMapping" + aws dynamodb create-table \ + --table-name featureFlagUserMapping \ + --attribute-definitions \ + AttributeName=userId,AttributeType=S \ + AttributeName=flagId,AttributeType=S \ + --key-schema \ + AttributeName=userId,KeyType=HASH \ + AttributeName=flagId,KeyType=RANGE \ + --billing-mode PAY_PER_REQUEST \ + --region "$REGION" \ + --no-cli-pager + echo "โœ… Created featureFlagUserMapping table" +else + echo "โญ๏ธ Table featureFlagUserMapping already exists, skipping creation" +fi echo "" # Table 3: requestLimit -echo "Creating table: requestLimit" -aws dynamodb create-table \ - --table-name requestLimit \ - --attribute-definitions \ - AttributeName=limitType,AttributeType=S \ - --key-schema \ - AttributeName=limitType,KeyType=HASH \ - --billing-mode PAY_PER_REQUEST \ - --region $REGION \ - --no-cli-pager - -echo "โœ… Created requestLimit table" +if ! table_exists "requestLimit"; then + echo "Creating table: requestLimit" + aws dynamodb create-table \ + --table-name requestLimit \ + --attribute-definitions \ + AttributeName=limitType,AttributeType=S \ + --key-schema \ + AttributeName=limitType,KeyType=HASH \ + --billing-mode PAY_PER_REQUEST \ + --region "$REGION" \ + --no-cli-pager + echo "โœ… Created requestLimit table" +else + echo "โญ๏ธ Table requestLimit already exists, skipping creation" +fi echo "" # Wait for tables to be active echo "โณ Waiting for tables to become active..." aws dynamodb wait table-exists \ --table-name featureFlag \ - --region $REGION + --region "$REGION" aws dynamodb wait table-exists \ --table-name featureFlagUserMapping \ - --region $REGION + --region "$REGION" aws dynamodb wait table-exists \ --table-name requestLimit \ - --region $REGION + --region "$REGION" echo "โœ… All tables are active!" echo "" -# Initialize requestLimit table with default value +# Initialize requestLimit table with default value (idempotent) echo "Initializing requestLimit table with default value..." -aws dynamodb put-item \ +# Check if item already exists +if ! aws dynamodb get-item \ --table-name requestLimit \ - --item '{ - "limitType": {"S": "pendingLimit"}, - "limitValue": {"N": "1000"} - }' \ - --region $REGION \ - --no-cli-pager - -echo "โœ… Initialized requestLimit with default value (1000)" + --key '{"limitType": {"S": "pendingLimit"}}' \ + --region "$REGION" \ + --no-cli-pager | grep -q "Item"; then + aws dynamodb put-item \ + --table-name requestLimit \ + --item '{ + "limitType": {"S": "pendingLimit"}, + "limitValue": {"N": "1000"} + }' \ + --region "$REGION" \ + --no-cli-pager + echo "โœ… Initialized requestLimit with default value (1000)" +else + echo "โญ๏ธ requestLimit already initialized, skipping" +fi echo "" echo "๐ŸŽ‰ All DynamoDB tables created and initialized successfully!" diff --git a/template.yaml b/template.yaml index 652fbb6..5d40f63 100644 --- a/template.yaml +++ b/template.yaml @@ -88,8 +88,14 @@ Resources: Layers: - !Ref SharedLayer Policies: - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" Events: Preflight: Type: Api @@ -114,8 +120,14 @@ Resources: TableName: featureFlag - DynamoDBCrudPolicy: TableName: featureFlagUserMapping - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" - SSMParameterReadPolicy: ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY - SSMParameterReadPolicy: @@ -145,7 +157,15 @@ Resources: - Effect: Allow Action: - lambda:PutFunctionConcurrency - Resource: '*' + Resource: + - !GetAtt CorsLambda.Arn + - !GetAtt CreateFeatureFlagFunction.Arn + - !GetAtt CreateUserFeatureFlagFunction.Arn + - !GetAtt GetFeatureFlagFunction.Arn + - !GetAtt GetUserFeatureFlagFunction.Arn + - !GetAtt GetAllFeatureFlagFunction.Arn + - !GetAtt UpdateFeatureFlagFunction.Arn + - !GetAtt GetUserFeatureFlagsFunction.Arn Events: CatchAll: Type: Api @@ -166,8 +186,14 @@ Resources: Layers: - !Ref SharedLayer Policies: - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" Events: CatchAll: Type: Api @@ -192,8 +218,14 @@ Resources: TableName: featureFlag - DynamoDBCrudPolicy: TableName: featureFlagUserMapping - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" - SSMParameterReadPolicy: ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY - SSMParameterReadPolicy: @@ -222,8 +254,14 @@ Resources: TableName: featureFlag - DynamoDBCrudPolicy: TableName: featureFlagUserMapping - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" - SSMParameterReadPolicy: ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY - SSMParameterReadPolicy: @@ -252,8 +290,14 @@ Resources: TableName: featureFlag - DynamoDBCrudPolicy: TableName: featureFlagUserMapping - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" - SSMParameterReadPolicy: ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY - SSMParameterReadPolicy: @@ -282,8 +326,14 @@ Resources: TableName: featureFlag - DynamoDBCrudPolicy: TableName: featureFlagUserMapping - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" - SSMParameterReadPolicy: ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY - SSMParameterReadPolicy: @@ -312,8 +362,14 @@ Resources: TableName: featureFlag - DynamoDBCrudPolicy: TableName: featureFlagUserMapping - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" - SSMParameterReadPolicy: ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY - SSMParameterReadPolicy: @@ -342,8 +398,14 @@ Resources: TableName: featureFlag - DynamoDBCrudPolicy: TableName: featureFlagUserMapping - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" - SSMParameterReadPolicy: ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY - SSMParameterReadPolicy: @@ -372,8 +434,14 @@ Resources: TableName: featureFlag - DynamoDBCrudPolicy: TableName: featureFlagUserMapping - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" - SSMParameterReadPolicy: ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY - SSMParameterReadPolicy: @@ -402,8 +470,14 @@ Resources: TableName: featureFlag - DynamoDBCrudPolicy: TableName: featureFlagUserMapping - - DynamoDBCrudPolicy: - TableName: requestLimit + - Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + Resource: + - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/requestLimit" - SSMParameterReadPolicy: ParameterName: PROD_RDS_BACKEND_PUBLIC_KEY - SSMParameterReadPolicy: From 74a2aa89247465dfbf9d1e0c01283b949fe09076 Mon Sep 17 00:00:00 2001 From: lakshayman Date: Fri, 16 Jan 2026 14:37:52 +0530 Subject: [PATCH 6/6] fix: added samconfig.toml in gitignore --- .gitignore | 3 ++- samconfig.toml | 15 --------------- 2 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 samconfig.toml diff --git a/.gitignore b/.gitignore index 0e2901b..728bbc0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .aws-sam/ .DS_Store -.env \ No newline at end of file +.env +samconfig.toml \ No newline at end of file diff --git a/samconfig.toml b/samconfig.toml deleted file mode 100644 index 5b02e46..0000000 --- a/samconfig.toml +++ /dev/null @@ -1,15 +0,0 @@ -version = 0.1 - -[default.deploy.parameters] -stack_name = "feature-flag-2" -resolve_s3 = true -s3_prefix = "feature-flag-2" -region = "us-east-1" -confirm_changeset = true -capabilities = "CAPABILITY_IAM" -disable_rollback = true -parameter_overrides = "Environment=\"PRODUCTION\"" -image_repositories = [] - -[default.global.parameters] -region = "us-east-1"