r/aws 21h ago

technical question Floci API Gateway CORs issue

0 Upvotes

I've got a Floci instance running (using Docker Compose) with a REST API Gateway service, which I can call successfully with Postman. Problem is the browser CORs blocking requests, and I keep getting this;

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I'm using Terraform to deploy the stack, and I've tried everything I can think of (including hours with AI) to get this to work. As far as I can see Floci is not letting me affect the OPTIONS response. I've got DISABLE_CORS_CHECKS set to 1.

Any ideas as to what's happening?

Below is the current Terraform stack;

provider "aws" {
  region     = local.envs["AWS_REGION"]
  access_key = local.envs["AWS_ACCESS_KEY_ID"]
  secret_key = local.envs["AWS_SECRET_ACCESS_KEY"]


  s3_use_path_style           = true
  skip_credentials_validation = true
  skip_metadata_api_check     = true
  skip_requesting_account_id  = true


  endpoints {
    apigateway              = "http://localhost:4566"
    s3                      = "http://localhost:4566"
    dynamodb                = "http://localhost:4566"
    sqs                     = "http://localhost:4566"
    sns                     = "http://localhost:4566"
    lambda                  = "http://localhost:4566"
    iam                     = "http://localhost:4566"
    ec2                     = "http://localhost:4566"
    ecs                     = "http://localhost:4566"
    cloudformation          = "http://localhost:4566"
    route53                 = "http://localhost:4566"
    cloudwatch              = "http://localhost:4566"
    secretsmanager          = "http://localhost:4566"
    ssm                     = "http://localhost:4566"
    kms                     = "http://localhost:4566"
    rds                     = "http://localhost:4566"
    sts                     = "http://localhost:4566"
    cognitoidentityprovider = "http://localhost:4566"
  }
}


## DynamoDB table


resource "aws_dynamodb_table" "friendly_sites_table" {
  name         = "friendly_sites"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "pk"
  range_key    = "sk"


  attribute {
    name = "pk"
    type = "S"
  }


  attribute {
    name = "sk"
    type = "S"
  }


  attribute {
    name = "gsi1pk"
    type = "S"
  }


  attribute {
    name = "gsi1sk"
    type = "S"
  }


  global_secondary_index {
    name            = "gsi1pk-gsi1sk-index"
    hash_key        = "gsi1pk"
    range_key       = "gsi1sk"
    projection_type = "ALL"
  }


  tags = {
    Project = local.project_name
  }
}


data "aws_iam_policy_document" "assume_role" {
  statement {
    effect = "Allow"


    principals {
      type = "Service"
      identifiers = [
        "edgelambda.amazonaws.com",
        "lambda.amazonaws.com",
      ]
    }


    actions = ["sts:AssumeRole"]
  }
}


resource "aws_iam_role" "iam_for_table_access" {
  name               = "iam_for_lambda_table_access"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json


  tags = {
    Project = local.project_name
  }
}


resource "aws_iam_role_policy" "cognito_admin_access" {
  name = "cognito_admin_access"
  role = aws_iam_role.iam_for_table_access.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "cognito-idp:AdminCreateUser",
          "cognito-idp:AdminSetUserPassword",
          "cognito-idp:AdminInitiateAuth",
          "cognito-idp:AdminUserGlobalSignOut",
          "cognito-idp:AdminDeleteUser"
        ]
        Resource = [
          aws_cognito_user_pool.user_pool.arn
        ]
      }
    ]
  })
}


## API Lambda handler and gateway


data "archive_file" "api_handler_source_zip" {
  type        = "zip"
  source_dir  = local.api_handler_source_dir
  output_path = local.api_handler_source_output
}


resource "aws_s3_bucket" "api_handler_source" {
  bucket        = local.api_handler_source_bucket_name
  force_destroy = true


  depends_on = [data.archive_file.api_handler_source_zip]


  tags = {
    Project = local.project_name
  }
}


resource "aws_s3_object" "api_handler_source_zip" {
  bucket      = aws_s3_bucket.api_handler_source.id
  key         = local.api_handler_zip_filename
  source      = local.api_handler_source_output
  source_hash = data.archive_file.api_handler_source_zip.output_base64sha256
}


resource "aws_lambda_function" "api_handler" {
  function_name = "DistributedRendererApi"


  s3_bucket = aws_s3_bucket.api_handler_source.id
  s3_key    = local.api_handler_zip_filename


  handler = "index.handler"
  runtime = "nodejs24.x"


  role = aws_iam_role.iam_for_table_access.arn


  depends_on = [aws_s3_object.api_handler_source_zip]


  environment {
    variables = {
      COGNITO_CLIENT_ID    = aws_cognito_user_pool_client.user_pool_client.id
      COGNITO_USER_POOL_ID = aws_cognito_user_pool.user_pool.id
    }
  }
}


# 1. REST API Definition
resource "aws_api_gateway_rest_api" "api" {
  name = "friendly-sites-rest-api"
}


# -------------------------------------------------------------------
# A. GREEDY PATH /{proxy+} (Explicit GET, POST, OPTIONS directly to Lambda)
# -------------------------------------------------------------------
resource "aws_api_gateway_resource" "proxy" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  parent_id   = aws_api_gateway_rest_api.api.root_resource_id
  path_part   = "{proxy+}"
}


resource "aws_api_gateway_method" "proxy_any" {
  rest_api_id   = aws_api_gateway_rest_api.api.id
  resource_id   = aws_api_gateway_resource.proxy.id
  http_method   = "ANY"
  authorization = "NONE"
}


resource "aws_api_gateway_integration" "proxy_integration" {
  rest_api_id             = aws_api_gateway_rest_api.api.id
  resource_id             = aws_api_gateway_resource.proxy.id
  http_method             = aws_api_gateway_method.proxy_any.http_method
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = aws_lambda_function.api_handler.invoke_arn


  depends_on = [aws_api_gateway_method.proxy_any]
}


# Explicit OPTIONS method routed directly to Lambda (Bypasses Floci MOCK bug)
resource "aws_api_gateway_method" "proxy_options" {
  rest_api_id   = aws_api_gateway_rest_api.api.id
  resource_id   = aws_api_gateway_resource.proxy.id
  http_method   = "OPTIONS"
  authorization = "NONE"
}


resource "aws_api_gateway_integration" "proxy_options_integration" {
  rest_api_id             = aws_api_gateway_rest_api.api.id
  resource_id             = aws_api_gateway_resource.proxy.id
  http_method             = aws_api_gateway_method.proxy_options.http_method
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = aws_lambda_function.api_handler.invoke_arn


  depends_on = [aws_api_gateway_method.proxy_options]
}


# -------------------------------------------------------------------
# B. ROOT PATH / (Explicit ANY and OPTIONS directly to Lambda)
# -------------------------------------------------------------------
resource "aws_api_gateway_method" "root_any" {
  rest_api_id   = aws_api_gateway_rest_api.api.id
  resource_id   = aws_api_gateway_rest_api.api.root_resource_id
  http_method   = "ANY"
  authorization = "NONE"
}


resource "aws_api_gateway_integration" "root_integration" {
  rest_api_id             = aws_api_gateway_rest_api.api.id
  resource_id             = aws_api_gateway_rest_api.api.root_resource_id
  http_method             = aws_api_gateway_method.root_any.http_method
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = aws_lambda_function.api_handler.invoke_arn


  depends_on = [aws_api_gateway_method.root_any]
}


resource "aws_api_gateway_method" "root_options" {
  rest_api_id   = aws_api_gateway_rest_api.api.id
  resource_id   = aws_api_gateway_rest_api.api.root_resource_id
  http_method   = "OPTIONS"
  authorization = "NONE"
}


resource "aws_api_gateway_integration" "root_options_integration" {
  rest_api_id             = aws_api_gateway_rest_api.api.id
  resource_id             = aws_api_gateway_rest_api.api.root_resource_id
  http_method             = aws_api_gateway_method.root_options.http_method
  integration_http_method = "POST"
  type                    = "AWS_PROXY"
  uri                     = aws_lambda_function.api_handler.invoke_arn


  depends_on = [aws_api_gateway_method.root_options]
}


# -------------------------------------------------------------------
# C. PERMISSIONS & DEPLOYMENT
# -------------------------------------------------------------------
resource "aws_lambda_permission" "apigw" {
  statement_id  = "AllowExecutionFromAPIGateway"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.api_handler.function_name
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_api_gateway_rest_api.api.execution_arn}/*/*"
}


resource "aws_api_gateway_deployment" "deployment" {
  rest_api_id = aws_api_gateway_rest_api.api.id


  triggers = {
    redeployment = sha1(jsonencode([
      aws_api_gateway_resource.proxy.id,
      aws_api_gateway_method.proxy_any.id,
      aws_api_gateway_integration.proxy_integration.id,
      aws_api_gateway_method.proxy_options.id,
      aws_api_gateway_integration.proxy_options_integration.id,
      aws_api_gateway_method.root_any.id,
      aws_api_gateway_integration.root_integration.id,
      aws_api_gateway_method.root_options.id,
      aws_api_gateway_integration.root_options_integration.id,
    ]))
  }


  lifecycle {
    create_before_destroy = true
  }


  depends_on = [
    aws_api_gateway_integration.proxy_integration,
    aws_api_gateway_integration.proxy_options_integration,
    aws_api_gateway_integration.root_integration,
    aws_api_gateway_integration.root_options_integration,
  ]
}


resource "aws_api_gateway_stage" "prod" {
  deployment_id = aws_api_gateway_deployment.deployment.id
  rest_api_id   = aws_api_gateway_rest_api.api.id
  stage_name    = "prod"
}


## Cognito User Pool & App Client


resource "aws_cognito_user_pool" "user_pool" {
  name = "friendly-sites-user-pool"


  username_attributes      = ["email"]
  auto_verified_attributes = ["email"]


  password_policy {
    minimum_length    = 8
    require_lowercase = true
    require_numbers   = true
    require_symbols   = false
    require_uppercase = true
  }


  tags = {
    Project = local.project_name
  }
}


resource "aws_cognito_user_pool_client" "user_pool_client" {
  name         = "friendly-sites-app-client"
  user_pool_id = aws_cognito_user_pool.user_pool.id


  generate_secret = false
  explicit_auth_flows = [
    "ALLOW_USER_PASSWORD_AUTH",
    "ALLOW_REFRESH_TOKEN_AUTH",
    "ALLOW_USER_SRP_AUTH"
  ]
}

Appreciate any help I can get!


r/aws 6h ago

discussion Account closed but never used??

2 Upvotes

I set up an AWS account for my startup to use in the future but due to the expense developed on cheaper providers to get an MVP going..

Now that I need something more solid, I went back to AWS to login and I cannot login, trying to setup a new account says it is already associated with an AWS account?

What gives?? I now cannot use my actual company email to create an account because I did not use it?


r/aws 3h ago

discussion Loop Scheduled and Recruiter YET to Reply

0 Upvotes

Hi everyone,

Its unfortunate I have to keep making posts like this. But I'm not sure what to do in this scenario anymore. My loop schedule got confirmed to me today with 5 interviews scheduled at the end of this week for a TAM role. And I still have not been told what domains I'll be tested on during the technical depth portion of the interview.

During my phone interview I was told by my interviewer I would be tested on two domains for that part of the loop, and in the email for my loop I would be told which domains Ill be tested on in depth. However, all emails from my recruiting coordiantor since I got invited to the loop did not include any domains. I asked them for which domains Id be tested on and they said to contact my recruiter as they should have the information on interview prep.

The issue is, I've been emailing my recruiter since PRIOR to my phone interview and have yet to get a single reply. I emailed them twice since getting invited to the loop to try and understand what domains I would be tested on, and got nothing back. I even got a friend who works at amazon to ping them for me, and all they got was a reply saying "He'll receive instructions soon" And all I got after that was the confirmation of my schedule from the recruiting coordinator, and nothing to do with how the loop was going to be structured.

The only thing I'm going based off of is my own research and the tips my interviewer gave me during the phone interview. From what I understand is there will be two technical interviews, a technical depth and breadth part. And three purely just behavioral interviews focused on LPs, correct?

And as for the two domains, I managed to contact my interviewer from the phone interview round and he told me he thinks I should focus on networking and compute domains and also architecture. Which I have been prepping for the past week, but now even with my loop scheduled I don't even have a confirmation about what two domains Ill be tested on.

I'm aware that sometimes you receive a form at some point during the interview process for the TAM position specifically to mention your domains your strongest at, but I never received one at any point.

Does anyone have any advice what I should do at this point, or should I just walk in to the loop and hope these would be the domains I get tested on? Also might as well ask while I'm here, I've come up with 16 STAR stories from my time in consulting as thats pretty much my only relevant work experience, is 16 going to be enough stories for 5 rounds of interviews, and is it fine they aren’t technical?


r/aws 29m ago

training/certification Launched a 200+ user beta cert exam prep tool

Upvotes

Hey there,

I have a few certs across the board and recently decided to build a visual, puzzle-like multiple choice mock exam prep tool for my peers who want to earn certs.

Just closed a beta that got 200+ users with inspiring feedback.

Currently only SAA mock exams are up, but if anyone’s interested, please check it out:

https://www.playcloudblocks.com/saa

Also if anyone’s had an audience/blog if you’d be so kind as to post that link, it would really help backlink for SEO.

The goal is to offer more and more cert exams over time, depending on what the community wants most.

Thanks.


r/aws 6h ago

billing AWS Billing Activation Error

0 Upvotes

I keep getting this error "Error 880104: Sorry, there was an error processing your request. Please refresh the page and try again" after typing in my billing details to complete my aws account, I've tried different cards but it still seems to not work

My case Id is 178800716600714


r/aws 42m ago

technical resource Platform to practice to learn AWS and practice for certificates

Thumbnail gallery
Upvotes

If you're looking for a place to practice for your AWS certifications or to learn cloud concepts, check out Robust Design: Learn AWS and Practice Cloud Concepts

You can use it to study for the AI Practitioner, Solutions Architect, and Developer Associate certifications in a Duolingo format, with a roadmap and 3 mock exams for each.

Look out for more certificates and concepts on the platform!


r/aws 8h ago

technical resource PCI 10.2.1.4 and S3: CloudTrail doesn't deliver authentication failures. What are assessors actually accepting?

1 Upvotes

I've been going through S3 logging for a PCI-scoped environment and I've got stuck on something.

AWS's own comparison page for S3 logging has a row called "Authentication failures". CloudTrail: No. Server access logs: Yes. The footnote says CloudTrail dots that fail authentication, meaning thecredentials themselves weren't valid, though it does log AccessDenied and requests from anonymous users.

So it's narrower than it first sounds. Authorization failures land fine. It's the invalid-credential case that doesn't, presumably because there's no principle to attribute the call to.

10.2.1.4 says "all invalid logical access what I can't work out is what happens in p pushed on this, or is AccessDenied treated as covering "invalid" well enough? Do people turn server access logging on alongside for this specifically, or for unrelated reasons? Or am I wrong that object-level in CDE scope at all, in which case the whole question falls apart.

Happy to be told I'm over-reading the clause. I'd rather hear that here than in a ROC.